chore: Cleanup void returns (#187)
* Place `return` in `return [void]` on separate line * format * Update CameraView+RecordVideo.swift * f
This commit is contained in:
parent
68a716b506
commit
16f2a7cdec
@ -31,7 +31,8 @@ extension CameraView {
|
|||||||
if enableAudio {
|
if enableAudio {
|
||||||
let audioPermissionStatus = AVCaptureDevice.authorizationStatus(for: .audio)
|
let audioPermissionStatus = AVCaptureDevice.authorizationStatus(for: .audio)
|
||||||
if audioPermissionStatus != .authorized {
|
if audioPermissionStatus != .authorized {
|
||||||
return invokeOnError(.permission(.microphone))
|
invokeOnError(.permission(.microphone))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,16 +45,19 @@ extension CameraView {
|
|||||||
if enableAudio {
|
if enableAudio {
|
||||||
ReactLogger.log(level: .info, message: "Adding Audio input...")
|
ReactLogger.log(level: .info, message: "Adding Audio input...")
|
||||||
guard let audioDevice = AVCaptureDevice.default(for: .audio) else {
|
guard let audioDevice = AVCaptureDevice.default(for: .audio) else {
|
||||||
return invokeOnError(.device(.microphoneUnavailable))
|
invokeOnError(.device(.microphoneUnavailable))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice)
|
audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice)
|
||||||
guard audioCaptureSession.canAddInput(audioDeviceInput!) else {
|
guard audioCaptureSession.canAddInput(audioDeviceInput!) else {
|
||||||
return invokeOnError(.parameter(.unsupportedInput(inputDescriptor: "audio-input")))
|
invokeOnError(.parameter(.unsupportedInput(inputDescriptor: "audio-input")))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
audioCaptureSession.addInput(audioDeviceInput!)
|
audioCaptureSession.addInput(audioDeviceInput!)
|
||||||
}
|
}
|
||||||
} catch let error as NSError {
|
} catch let error as NSError {
|
||||||
return invokeOnError(.device(.microphoneUnavailable), cause: error)
|
invokeOnError(.device(.microphoneUnavailable), cause: error)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio Output
|
// Audio Output
|
||||||
@ -65,7 +69,8 @@ extension CameraView {
|
|||||||
ReactLogger.log(level: .info, message: "Adding Audio Data output...")
|
ReactLogger.log(level: .info, message: "Adding Audio Data output...")
|
||||||
audioOutput = AVCaptureAudioDataOutput()
|
audioOutput = AVCaptureAudioDataOutput()
|
||||||
guard audioCaptureSession.canAddOutput(audioOutput!) else {
|
guard audioCaptureSession.canAddOutput(audioOutput!) else {
|
||||||
return invokeOnError(.parameter(.unsupportedOutput(outputDescriptor: "audio-output")))
|
invokeOnError(.parameter(.unsupportedOutput(outputDescriptor: "audio-output")))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
audioOutput!.setSampleBufferDelegate(self, queue: audioQueue)
|
audioOutput!.setSampleBufferDelegate(self, queue: audioQueue)
|
||||||
audioCaptureSession.addOutput(audioOutput!)
|
audioCaptureSession.addOutput(audioOutput!)
|
||||||
|
@ -23,11 +23,13 @@ extension CameraView {
|
|||||||
isReady = false
|
isReady = false
|
||||||
|
|
||||||
#if targetEnvironment(simulator)
|
#if targetEnvironment(simulator)
|
||||||
return invokeOnError(.device(.notAvailableOnSimulator))
|
invokeOnError(.device(.notAvailableOnSimulator))
|
||||||
|
return
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
guard cameraId != nil else {
|
guard cameraId != nil else {
|
||||||
return invokeOnError(.device(.noDevice))
|
invokeOnError(.device(.noDevice))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
let cameraId = self.cameraId! as String
|
let cameraId = self.cameraId! as String
|
||||||
|
|
||||||
@ -43,9 +45,11 @@ extension CameraView {
|
|||||||
do {
|
do {
|
||||||
sessionPreset = try AVCaptureSession.Preset(withString: preset)
|
sessionPreset = try AVCaptureSession.Preset(withString: preset)
|
||||||
} catch let EnumParserError.unsupportedOS(supportedOnOS: os) {
|
} catch let EnumParserError.unsupportedOS(supportedOnOS: os) {
|
||||||
return invokeOnError(.parameter(.unsupportedOS(unionName: "Preset", receivedValue: preset, supportedOnOs: os)))
|
invokeOnError(.parameter(.unsupportedOS(unionName: "Preset", receivedValue: preset, supportedOnOs: os)))
|
||||||
|
return
|
||||||
} catch {
|
} catch {
|
||||||
return invokeOnError(.parameter(.invalid(unionName: "Preset", receivedValue: preset)))
|
invokeOnError(.parameter(.invalid(unionName: "Preset", receivedValue: preset)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if sessionPreset != nil {
|
if sessionPreset != nil {
|
||||||
if captureSession.canSetSessionPreset(sessionPreset!) {
|
if captureSession.canSetSessionPreset(sessionPreset!) {
|
||||||
@ -66,15 +70,18 @@ extension CameraView {
|
|||||||
}
|
}
|
||||||
ReactLogger.log(level: .info, message: "Adding Video input...")
|
ReactLogger.log(level: .info, message: "Adding Video input...")
|
||||||
guard let videoDevice = AVCaptureDevice(uniqueID: cameraId) else {
|
guard let videoDevice = AVCaptureDevice(uniqueID: cameraId) else {
|
||||||
return invokeOnError(.device(.invalid))
|
invokeOnError(.device(.invalid))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice)
|
videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice)
|
||||||
guard captureSession.canAddInput(videoDeviceInput!) else {
|
guard captureSession.canAddInput(videoDeviceInput!) else {
|
||||||
return invokeOnError(.parameter(.unsupportedInput(inputDescriptor: "video-input")))
|
invokeOnError(.parameter(.unsupportedInput(inputDescriptor: "video-input")))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
captureSession.addInput(videoDeviceInput!)
|
captureSession.addInput(videoDeviceInput!)
|
||||||
} catch {
|
} catch {
|
||||||
return invokeOnError(.device(.invalid))
|
invokeOnError(.device(.invalid))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// pragma MARK: Capture Session Outputs
|
// pragma MARK: Capture Session Outputs
|
||||||
@ -95,7 +102,8 @@ extension CameraView {
|
|||||||
photoOutput!.isPortraitEffectsMatteDeliveryEnabled = photoOutput!.isPortraitEffectsMatteDeliverySupported && self.enablePortraitEffectsMatteDelivery
|
photoOutput!.isPortraitEffectsMatteDeliveryEnabled = photoOutput!.isPortraitEffectsMatteDeliverySupported && self.enablePortraitEffectsMatteDelivery
|
||||||
}
|
}
|
||||||
guard captureSession.canAddOutput(photoOutput!) else {
|
guard captureSession.canAddOutput(photoOutput!) else {
|
||||||
return invokeOnError(.parameter(.unsupportedOutput(outputDescriptor: "photo-output")))
|
invokeOnError(.parameter(.unsupportedOutput(outputDescriptor: "photo-output")))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
captureSession.addOutput(photoOutput!)
|
captureSession.addOutput(photoOutput!)
|
||||||
if videoDeviceInput!.device.position == .front {
|
if videoDeviceInput!.device.position == .front {
|
||||||
@ -112,7 +120,8 @@ extension CameraView {
|
|||||||
ReactLogger.log(level: .info, message: "Adding Video Data output...")
|
ReactLogger.log(level: .info, message: "Adding Video Data output...")
|
||||||
videoOutput = AVCaptureVideoDataOutput()
|
videoOutput = AVCaptureVideoDataOutput()
|
||||||
guard captureSession.canAddOutput(videoOutput!) else {
|
guard captureSession.canAddOutput(videoOutput!) else {
|
||||||
return invokeOnError(.parameter(.unsupportedOutput(outputDescriptor: "video-output")))
|
invokeOnError(.parameter(.unsupportedOutput(outputDescriptor: "video-output")))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
videoOutput!.setSampleBufferDelegate(self, queue: videoQueue)
|
videoOutput!.setSampleBufferDelegate(self, queue: videoQueue)
|
||||||
videoOutput!.alwaysDiscardsLateVideoFrames = true
|
videoOutput!.alwaysDiscardsLateVideoFrames = true
|
||||||
@ -135,7 +144,8 @@ extension CameraView {
|
|||||||
final func configureDevice() {
|
final func configureDevice() {
|
||||||
ReactLogger.log(level: .info, message: "Configuring Device...")
|
ReactLogger.log(level: .info, message: "Configuring Device...")
|
||||||
guard let device = videoDeviceInput?.device else {
|
guard let device = videoDeviceInput?.device else {
|
||||||
return invokeOnError(.session(.cameraNotReady))
|
invokeOnError(.session(.cameraNotReady))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -151,7 +161,8 @@ extension CameraView {
|
|||||||
}
|
}
|
||||||
if hdr != nil {
|
if hdr != nil {
|
||||||
if hdr == true && !device.activeFormat.isVideoHDRSupported {
|
if hdr == true && !device.activeFormat.isVideoHDRSupported {
|
||||||
return invokeOnError(.format(.invalidHdr))
|
invokeOnError(.format(.invalidHdr))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if !device.automaticallyAdjustsVideoHDREnabled {
|
if !device.automaticallyAdjustsVideoHDREnabled {
|
||||||
if device.isVideoHDREnabled != hdr!.boolValue {
|
if device.isVideoHDREnabled != hdr!.boolValue {
|
||||||
@ -161,7 +172,8 @@ extension CameraView {
|
|||||||
}
|
}
|
||||||
if lowLightBoost != nil {
|
if lowLightBoost != nil {
|
||||||
if lowLightBoost == true && !device.isLowLightBoostSupported {
|
if lowLightBoost == true && !device.isLowLightBoostSupported {
|
||||||
return invokeOnError(.device(.lowLightBoostNotSupported))
|
invokeOnError(.device(.lowLightBoostNotSupported))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if device.automaticallyEnablesLowLightBoostWhenAvailable != lowLightBoost!.boolValue {
|
if device.automaticallyEnablesLowLightBoostWhenAvailable != lowLightBoost!.boolValue {
|
||||||
device.automaticallyEnablesLowLightBoostWhenAvailable = lowLightBoost!.boolValue
|
device.automaticallyEnablesLowLightBoostWhenAvailable = lowLightBoost!.boolValue
|
||||||
@ -174,7 +186,8 @@ extension CameraView {
|
|||||||
device.unlockForConfiguration()
|
device.unlockForConfiguration()
|
||||||
ReactLogger.log(level: .info, message: "Device successfully configured!")
|
ReactLogger.log(level: .info, message: "Device successfully configured!")
|
||||||
} catch let error as NSError {
|
} catch let error as NSError {
|
||||||
return invokeOnError(.device(.configureError), cause: error)
|
invokeOnError(.device(.configureError), cause: error)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +203,8 @@ extension CameraView {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let device = videoDeviceInput?.device else {
|
guard let device = videoDeviceInput?.device else {
|
||||||
return invokeOnError(.session(.cameraNotReady))
|
invokeOnError(.session(.cameraNotReady))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if device.activeFormat.matchesFilter(filter) {
|
if device.activeFormat.matchesFilter(filter) {
|
||||||
@ -201,7 +215,8 @@ extension CameraView {
|
|||||||
// get matching format
|
// get matching format
|
||||||
let matchingFormats = device.formats.filter { $0.matchesFilter(filter) }.sorted { $0.isBetterThan($1) }
|
let matchingFormats = device.formats.filter { $0.matchesFilter(filter) }.sorted { $0.isBetterThan($1) }
|
||||||
guard let format = matchingFormats.first else {
|
guard let format = matchingFormats.first else {
|
||||||
return invokeOnError(.format(.invalidFormat))
|
invokeOnError(.format(.invalidFormat))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -210,7 +225,8 @@ extension CameraView {
|
|||||||
device.unlockForConfiguration()
|
device.unlockForConfiguration()
|
||||||
ReactLogger.log(level: .info, message: "Format successfully configured!")
|
ReactLogger.log(level: .info, message: "Format successfully configured!")
|
||||||
} catch let error as NSError {
|
} catch let error as NSError {
|
||||||
return invokeOnError(.device(.configureError), cause: error)
|
invokeOnError(.device(.configureError), cause: error)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
var fileType = AVFileType.mov
|
var fileType = AVFileType.mov
|
||||||
if let fileTypeOption = options["fileType"] as? String {
|
if let fileTypeOption = options["fileType"] as? String {
|
||||||
guard let parsed = try? AVFileType(withString: fileTypeOption) else {
|
guard let parsed = try? AVFileType(withString: fileTypeOption) else {
|
||||||
return callback.reject(error: .parameter(.invalid(unionName: "fileType", receivedValue: fileTypeOption)))
|
callback.reject(error: .parameter(.invalid(unionName: "fileType", receivedValue: fileTypeOption)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
fileType = parsed
|
fileType = parsed
|
||||||
}
|
}
|
||||||
@ -32,7 +33,8 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
let errorPointer = ErrorPointer(nilLiteral: ())
|
let errorPointer = ErrorPointer(nilLiteral: ())
|
||||||
let fileExtension = fileType.descriptor ?? "mov"
|
let fileExtension = fileType.descriptor ?? "mov"
|
||||||
guard let tempFilePath = RCTTempFilePath(fileExtension, errorPointer) else {
|
guard let tempFilePath = RCTTempFilePath(fileExtension, errorPointer) else {
|
||||||
return callback.reject(error: .capture(.createTempFileError), cause: errorPointer?.pointee)
|
callback.reject(error: .capture(.createTempFileError), cause: errorPointer?.pointee)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactLogger.log(level: .info, message: "File path: \(tempFilePath)")
|
ReactLogger.log(level: .info, message: "File path: \(tempFilePath)")
|
||||||
@ -45,9 +47,11 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
|
|
||||||
guard let videoOutput = self.videoOutput else {
|
guard let videoOutput = self.videoOutput else {
|
||||||
if self.video?.boolValue == true {
|
if self.video?.boolValue == true {
|
||||||
return callback.reject(error: .session(.cameraNotReady))
|
callback.reject(error: .session(.cameraNotReady))
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
return callback.reject(error: .capture(.videoNotEnabled))
|
callback.reject(error: .capture(.videoNotEnabled))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +62,7 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
|
|
||||||
let enableAudio = self.audio?.boolValue == true
|
let enableAudio = self.audio?.boolValue == true
|
||||||
|
|
||||||
let onFinish = { (status: AVAssetWriter.Status, error: Error?) -> Void in
|
let onFinish = { (status: AVAssetWriter.Status, error: Error?) in
|
||||||
defer {
|
defer {
|
||||||
self.recordingSession = nil
|
self.recordingSession = nil
|
||||||
if enableAudio {
|
if enableAudio {
|
||||||
@ -69,16 +73,15 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
}
|
}
|
||||||
ReactLogger.log(level: .info, message: "RecordingSession finished with status \(status.descriptor).")
|
ReactLogger.log(level: .info, message: "RecordingSession finished with status \(status.descriptor).")
|
||||||
if let error = error as NSError? {
|
if let error = error as NSError? {
|
||||||
let description = error.description
|
callback.reject(error: .capture(.unknown(message: "An unknown recording error occured! \(error.description)")), cause: error)
|
||||||
return callback.reject(error: .capture(.unknown(message: "An unknown recording error occured! \(description)")), cause: error)
|
|
||||||
} else {
|
} else {
|
||||||
if status == .completed {
|
if status == .completed {
|
||||||
return callback.resolve([
|
callback.resolve([
|
||||||
"path": self.recordingSession!.url.absoluteString,
|
"path": self.recordingSession!.url.absoluteString,
|
||||||
"duration": self.recordingSession!.duration,
|
"duration": self.recordingSession!.duration,
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
return callback.reject(error: .unknown(message: "AVAssetWriter completed with status: \(status.descriptor)"))
|
callback.reject(error: .unknown(message: "AVAssetWriter completed with status: \(status.descriptor)"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,13 +91,15 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
fileType: fileType,
|
fileType: fileType,
|
||||||
completion: onFinish)
|
completion: onFinish)
|
||||||
} catch let error as NSError {
|
} catch let error as NSError {
|
||||||
return callback.reject(error: .capture(.createRecorderError(message: nil)), cause: error)
|
callback.reject(error: .capture(.createRecorderError(message: nil)), cause: error)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init Video
|
// Init Video
|
||||||
guard let videoSettings = videoOutput.recommendedVideoSettingsForAssetWriter(writingTo: fileType),
|
guard let videoSettings = videoOutput.recommendedVideoSettingsForAssetWriter(writingTo: fileType),
|
||||||
!videoSettings.isEmpty else {
|
!videoSettings.isEmpty else {
|
||||||
return callback.reject(error: .capture(.createRecorderError(message: "Failed to get video settings!")))
|
callback.reject(error: .capture(.createRecorderError(message: "Failed to get video settings!")))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
self.recordingSession!.initializeVideoWriter(withSettings: videoSettings,
|
self.recordingSession!.initializeVideoWriter(withSettings: videoSettings,
|
||||||
isVideoMirrored: self.videoOutput!.isMirrored)
|
isVideoMirrored: self.videoOutput!.isMirrored)
|
||||||
@ -172,7 +177,8 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
|
|||||||
// Video Recording runs in the same queue
|
// Video Recording runs in the same queue
|
||||||
if isRecording {
|
if isRecording {
|
||||||
guard let recordingSession = recordingSession else {
|
guard let recordingSession = recordingSession else {
|
||||||
return invokeOnError(.capture(.unknown(message: "isRecording was true but the RecordingSession was null!")))
|
invokeOnError(.capture(.unknown(message: "isRecording was true but the RecordingSession was null!")))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch captureOutput {
|
switch captureOutput {
|
||||||
|
@ -28,26 +28,31 @@ extension CameraView {
|
|||||||
guard let photoOutput = self.photoOutput,
|
guard let photoOutput = self.photoOutput,
|
||||||
let videoDeviceInput = self.videoDeviceInput else {
|
let videoDeviceInput = self.videoDeviceInput else {
|
||||||
if self.photo?.boolValue == true {
|
if self.photo?.boolValue == true {
|
||||||
return promise.reject(error: .session(.cameraNotReady))
|
promise.reject(error: .session(.cameraNotReady))
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
return promise.reject(error: .capture(.photoNotEnabled))
|
promise.reject(error: .capture(.photoNotEnabled))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var photoSettings = AVCapturePhotoSettings()
|
var photoSettings = AVCapturePhotoSettings()
|
||||||
if let photoCodecString = options["photoCodec"] as? String {
|
if let photoCodecString = options["photoCodec"] as? String {
|
||||||
guard let photoCodec = AVVideoCodecType(withString: photoCodecString) else {
|
guard let photoCodec = AVVideoCodecType(withString: photoCodecString) else {
|
||||||
return promise.reject(error: .capture(.invalidPhotoCodec))
|
promise.reject(error: .capture(.invalidPhotoCodec))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if photoOutput.availablePhotoCodecTypes.contains(photoCodec) {
|
if photoOutput.availablePhotoCodecTypes.contains(photoCodec) {
|
||||||
photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: photoCodec])
|
photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: photoCodec])
|
||||||
} else {
|
} else {
|
||||||
return promise.reject(error: .parameter(.invalid(unionName: "PhotoCodec", receivedValue: photoCodecString)))
|
promise.reject(error: .parameter(.invalid(unionName: "PhotoCodec", receivedValue: photoCodecString)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if videoDeviceInput.device.isFlashAvailable, let flash = options["flash"] as? String {
|
if videoDeviceInput.device.isFlashAvailable, let flash = options["flash"] as? String {
|
||||||
guard let flashMode = AVCaptureDevice.FlashMode(withString: flash) else {
|
guard let flashMode = AVCaptureDevice.FlashMode(withString: flash) else {
|
||||||
return promise.reject(error: .parameter(.invalid(unionName: "FlashMode", receivedValue: flash)))
|
promise.reject(error: .parameter(.invalid(unionName: "FlashMode", receivedValue: flash)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
photoSettings.flashMode = flashMode
|
photoSettings.flashMode = flashMode
|
||||||
}
|
}
|
||||||
@ -63,7 +68,8 @@ extension CameraView {
|
|||||||
}
|
}
|
||||||
if #available(iOS 13.0, *), let qualityPrioritization = options["qualityPrioritization"] as? String {
|
if #available(iOS 13.0, *), let qualityPrioritization = options["qualityPrioritization"] as? String {
|
||||||
guard let photoQualityPrioritization = AVCapturePhotoOutput.QualityPrioritization(withString: qualityPrioritization) else {
|
guard let photoQualityPrioritization = AVCapturePhotoOutput.QualityPrioritization(withString: qualityPrioritization) else {
|
||||||
return promise.reject(error: .parameter(.invalid(unionName: "QualityPrioritization", receivedValue: qualityPrioritization)))
|
promise.reject(error: .parameter(.invalid(unionName: "QualityPrioritization", receivedValue: qualityPrioritization)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
photoSettings.photoQualityPrioritization = photoQualityPrioritization
|
photoSettings.photoQualityPrioritization = photoQualityPrioritization
|
||||||
}
|
}
|
||||||
|
@ -227,10 +227,12 @@ public final class CameraView: UIView {
|
|||||||
|
|
||||||
internal final func setTorchMode(_ torchMode: String) {
|
internal final func setTorchMode(_ torchMode: String) {
|
||||||
guard let device = videoDeviceInput?.device else {
|
guard let device = videoDeviceInput?.device else {
|
||||||
return invokeOnError(.session(.cameraNotReady))
|
invokeOnError(.session(.cameraNotReady))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
guard var torchMode = AVCaptureDevice.TorchMode(withString: torchMode) else {
|
guard var torchMode = AVCaptureDevice.TorchMode(withString: torchMode) else {
|
||||||
return invokeOnError(.parameter(.invalid(unionName: "TorchMode", receivedValue: torch)))
|
invokeOnError(.parameter(.invalid(unionName: "TorchMode", receivedValue: torch)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if !captureSession.isRunning {
|
if !captureSession.isRunning {
|
||||||
torchMode = .off
|
torchMode = .off
|
||||||
@ -245,7 +247,8 @@ public final class CameraView: UIView {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
// torch mode is .auto or .on, but no torch is available.
|
// torch mode is .auto or .on, but no torch is available.
|
||||||
return invokeOnError(.device(.torchUnavailable))
|
invokeOnError(.device(.torchUnavailable))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
@ -256,7 +259,8 @@ public final class CameraView: UIView {
|
|||||||
}
|
}
|
||||||
device.unlockForConfiguration()
|
device.unlockForConfiguration()
|
||||||
} catch let error as NSError {
|
} catch let error as NSError {
|
||||||
return invokeOnError(.device(.configureError), cause: error)
|
invokeOnError(.device(.configureError), cause: error)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,8 @@ final class CameraViewManager: RCTViewManager {
|
|||||||
final func focus(_ node: NSNumber, point: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
final func focus(_ node: NSNumber, point: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
||||||
let promise = Promise(resolver: resolve, rejecter: reject)
|
let promise = Promise(resolver: resolve, rejecter: reject)
|
||||||
guard let x = point["x"] as? NSNumber, let y = point["y"] as? NSNumber else {
|
guard let x = point["x"] as? NSNumber, let y = point["y"] as? NSNumber else {
|
||||||
return promise.reject(error: .parameter(.invalid(unionName: "point", receivedValue: point.description)))
|
promise.reject(error: .parameter(.invalid(unionName: "point", receivedValue: point.description)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
let component = getCameraView(withTag: node)
|
let component = getCameraView(withTag: node)
|
||||||
component.focus(point: CGPoint(x: x.doubleValue, y: y.doubleValue), promise: promise)
|
component.focus(point: CGPoint(x: x.doubleValue, y: y.doubleValue), promise: promise)
|
||||||
|
@ -63,11 +63,11 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
#ifdef ENABLE_FRAME_PROCESSORS
|
#ifdef ENABLE_FRAME_PROCESSORS
|
||||||
NSLog(@"FrameProcessorBindings: Creating Runtime Manager...");
|
NSLog(@"FrameProcessorBindings: Creating Runtime Manager...");
|
||||||
weakBridge = bridge;
|
weakBridge = bridge;
|
||||||
|
|
||||||
auto runtime = vision::makeJSIRuntime();
|
auto runtime = vision::makeJSIRuntime();
|
||||||
reanimated::RuntimeDecorator::decorateRuntime(*runtime, "FRAME_PROCESSOR");
|
reanimated::RuntimeDecorator::decorateRuntime(*runtime, "FRAME_PROCESSOR");
|
||||||
runtime->global().setProperty(*runtime, "_FRAME_PROCESSOR", jsi::Value(true));
|
runtime->global().setProperty(*runtime, "_FRAME_PROCESSOR", jsi::Value(true));
|
||||||
|
|
||||||
auto callInvoker = bridge.jsCallInvoker;
|
auto callInvoker = bridge.jsCallInvoker;
|
||||||
auto scheduler = std::make_shared<reanimated::REAIOSScheduler>(callInvoker);
|
auto scheduler = std::make_shared<reanimated::REAIOSScheduler>(callInvoker);
|
||||||
runtimeManager = std::make_unique<reanimated::RuntimeManager>(std::move(runtime),
|
runtimeManager = std::make_unique<reanimated::RuntimeManager>(std::move(runtime),
|
||||||
@ -78,7 +78,7 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
NSLog(@"FrameProcessorBindings: Installing Frame Processor plugins...");
|
NSLog(@"FrameProcessorBindings: Installing Frame Processor plugins...");
|
||||||
auto& visionRuntime = *runtimeManager->runtime;
|
auto& visionRuntime = *runtimeManager->runtime;
|
||||||
auto visionGlobal = visionRuntime.global();
|
auto visionGlobal = visionRuntime.global();
|
||||||
|
|
||||||
for (NSString* pluginKey in [FrameProcessorPluginRegistry frameProcessorPlugins]) {
|
for (NSString* pluginKey in [FrameProcessorPluginRegistry frameProcessorPlugins]) {
|
||||||
auto pluginName = [pluginKey UTF8String];
|
auto pluginName = [pluginKey UTF8String];
|
||||||
|
|
||||||
@ -89,18 +89,16 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
const jsi::Value& thisValue,
|
const jsi::Value& thisValue,
|
||||||
const jsi::Value* arguments,
|
const jsi::Value* arguments,
|
||||||
size_t count) -> jsi::Value {
|
size_t count) -> jsi::Value {
|
||||||
|
|
||||||
auto frameHostObject = arguments[0].asObject(runtime).asHostObject(runtime);
|
auto frameHostObject = arguments[0].asObject(runtime).asHostObject(runtime);
|
||||||
auto frame = static_cast<FrameHostObject*>(frameHostObject.get());
|
auto frame = static_cast<FrameHostObject*>(frameHostObject.get());
|
||||||
|
|
||||||
auto args = convertJSICStyleArrayToNSArray(runtime,
|
auto args = convertJSICStyleArrayToNSArray(runtime,
|
||||||
arguments + 1, // start at index 1 since first arg = Frame
|
arguments + 1, // start at index 1 since first arg = Frame
|
||||||
count - 1, // use smaller count
|
count - 1, // use smaller count
|
||||||
callInvoker);
|
callInvoker);
|
||||||
id result = callback(frame->frame, args);
|
id result = callback(frame->frame, args);
|
||||||
|
|
||||||
return convertObjCObjectToJSIValue(runtime, result);
|
return convertObjCObjectToJSIValue(runtime, result);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
visionGlobal.setProperty(visionRuntime, pluginName, jsi::Function::createFromHostFunction(visionRuntime,
|
visionGlobal.setProperty(visionRuntime, pluginName, jsi::Function::createFromHostFunction(visionRuntime,
|
||||||
@ -108,9 +106,9 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
1, // frame
|
1, // frame
|
||||||
function));
|
function));
|
||||||
}
|
}
|
||||||
|
|
||||||
[FrameProcessorPluginRegistry markInvalid];
|
[FrameProcessorPluginRegistry markInvalid];
|
||||||
|
|
||||||
NSLog(@"FrameProcessorBindings: Frame Processor plugins installed!");
|
NSLog(@"FrameProcessorBindings: Frame Processor plugins installed!");
|
||||||
#else
|
#else
|
||||||
NSLog(@"Reanimated not found, Frame Processors are disabled.");
|
NSLog(@"Reanimated not found, Frame Processors are disabled.");
|
||||||
@ -125,13 +123,13 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
NSLog(@"FrameProcessorBindings: Failed to install Frame Processor Bindings - bridge was null!");
|
NSLog(@"FrameProcessorBindings: Failed to install Frame Processor Bindings - bridge was null!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSLog(@"FrameProcessorBindings: Installing Frame Processor Bindings for Bridge...");
|
NSLog(@"FrameProcessorBindings: Installing Frame Processor Bindings for Bridge...");
|
||||||
RCTCxxBridge *cxxBridge = (RCTCxxBridge *)weakBridge;
|
RCTCxxBridge *cxxBridge = (RCTCxxBridge *)weakBridge;
|
||||||
if (!cxxBridge.runtime) {
|
if (!cxxBridge.runtime) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsi::Runtime& jsiRuntime = *(jsi::Runtime*)cxxBridge.runtime;
|
jsi::Runtime& jsiRuntime = *(jsi::Runtime*)cxxBridge.runtime;
|
||||||
NSLog(@"FrameProcessorBindings: Installing global functions...");
|
NSLog(@"FrameProcessorBindings: Installing global functions...");
|
||||||
|
|
||||||
@ -150,16 +148,16 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
auto worklet = reanimated::ShareableValue::adapt(runtime, arguments[1], runtimeManager.get());
|
auto worklet = reanimated::ShareableValue::adapt(runtime, arguments[1], runtimeManager.get());
|
||||||
NSLog(@"FrameProcessorBindings: Successfully created worklet!");
|
NSLog(@"FrameProcessorBindings: Successfully created worklet!");
|
||||||
|
|
||||||
RCTExecuteOnMainQueue([worklet, viewTag, self]() -> void {
|
RCTExecuteOnMainQueue([worklet, viewTag, self]() {
|
||||||
auto currentBridge = [RCTBridge currentBridge];
|
auto currentBridge = [RCTBridge currentBridge];
|
||||||
auto anonymousView = [currentBridge.uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]];
|
auto anonymousView = [currentBridge.uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]];
|
||||||
auto view = static_cast<CameraView*>(anonymousView);
|
auto view = static_cast<CameraView*>(anonymousView);
|
||||||
|
|
||||||
dispatch_async(CameraQueues.videoQueue, [worklet, view, self]() -> void {
|
dispatch_async(CameraQueues.videoQueue, [worklet, view, self]() {
|
||||||
NSLog(@"FrameProcessorBindings: Converting worklet to Objective-C callback...");
|
NSLog(@"FrameProcessorBindings: Converting worklet to Objective-C callback...");
|
||||||
auto& rt = *runtimeManager->runtime;
|
auto& rt = *runtimeManager->runtime;
|
||||||
auto function = worklet->getValue(rt).asObject(rt).asFunction(rt);
|
auto function = worklet->getValue(rt).asObject(rt).asFunction(rt);
|
||||||
|
|
||||||
view.frameProcessorCallback = convertJSIFunctionToFrameProcessorCallback(rt, function);
|
view.frameProcessorCallback = convertJSIFunctionToFrameProcessorCallback(rt, function);
|
||||||
NSLog(@"FrameProcessorBindings: Frame processor set!");
|
NSLog(@"FrameProcessorBindings: Frame processor set!");
|
||||||
});
|
});
|
||||||
@ -184,10 +182,10 @@ __attribute__((objc_runtime_name("_TtC12VisionCamera10CameraView")))
|
|||||||
RCTExecuteOnMainQueue(^{
|
RCTExecuteOnMainQueue(^{
|
||||||
auto currentBridge = [RCTBridge currentBridge];
|
auto currentBridge = [RCTBridge currentBridge];
|
||||||
if (!currentBridge) return;
|
if (!currentBridge) return;
|
||||||
|
|
||||||
auto anonymousView = [currentBridge.uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]];
|
auto anonymousView = [currentBridge.uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]];
|
||||||
if (!anonymousView) return;
|
if (!anonymousView) return;
|
||||||
|
|
||||||
auto view = static_cast<CameraView*>(anonymousView);
|
auto view = static_cast<CameraView*>(anonymousView);
|
||||||
view.frameProcessorCallback = nil;
|
view.frameProcessorCallback = nil;
|
||||||
NSLog(@"FrameProcessorBindings: Frame processor removed!");
|
NSLog(@"FrameProcessorBindings: Frame processor removed!");
|
||||||
|
@ -13,6 +13,8 @@ private var delegatesReferences: [NSObject] = []
|
|||||||
// MARK: - PhotoCaptureDelegate
|
// MARK: - PhotoCaptureDelegate
|
||||||
|
|
||||||
class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate {
|
class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate {
|
||||||
|
private let promise: Promise
|
||||||
|
|
||||||
required init(promise: Promise) {
|
required init(promise: Promise) {
|
||||||
self.promise = promise
|
self.promise = promise
|
||||||
super.init()
|
super.init()
|
||||||
@ -24,19 +26,21 @@ class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate {
|
|||||||
delegatesReferences.removeAll(where: { $0 == self })
|
delegatesReferences.removeAll(where: { $0 == self })
|
||||||
}
|
}
|
||||||
if let error = error as NSError? {
|
if let error = error as NSError? {
|
||||||
return promise.reject(error: .capture(.unknown(message: error.description)), cause: error)
|
promise.reject(error: .capture(.unknown(message: error.description)), cause: error)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = ErrorPointer(nilLiteral: ())
|
let error = ErrorPointer(nilLiteral: ())
|
||||||
guard let tempFilePath = RCTTempFilePath("jpeg", error)
|
guard let tempFilePath = RCTTempFilePath("jpeg", error)
|
||||||
else {
|
else {
|
||||||
return promise.reject(error: .capture(.createTempFileError), cause: error?.pointee)
|
promise.reject(error: .capture(.createTempFileError), cause: error?.pointee)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
let url = URL(string: "file://\(tempFilePath)")!
|
let url = URL(string: "file://\(tempFilePath)")!
|
||||||
|
|
||||||
guard let data = photo.fileDataRepresentation()
|
guard let data = photo.fileDataRepresentation() else {
|
||||||
else {
|
promise.reject(error: .capture(.fileError))
|
||||||
return promise.reject(error: .capture(.fileError))
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -45,7 +49,7 @@ class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate {
|
|||||||
let width = exif?["PixelXDimension"]
|
let width = exif?["PixelXDimension"]
|
||||||
let height = exif?["PixelYDimension"]
|
let height = exif?["PixelYDimension"]
|
||||||
|
|
||||||
return promise.resolve([
|
promise.resolve([
|
||||||
"path": tempFilePath,
|
"path": tempFilePath,
|
||||||
"width": width as Any,
|
"width": width as Any,
|
||||||
"height": height as Any,
|
"height": height as Any,
|
||||||
@ -54,7 +58,7 @@ class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate {
|
|||||||
"thumbnail": photo.embeddedThumbnailPhotoFormat as Any,
|
"thumbnail": photo.embeddedThumbnailPhotoFormat as Any,
|
||||||
])
|
])
|
||||||
} catch {
|
} catch {
|
||||||
return promise.reject(error: .capture(.fileError), cause: error as NSError)
|
promise.reject(error: .capture(.fileError), cause: error as NSError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,11 +67,8 @@ class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate {
|
|||||||
delegatesReferences.removeAll(where: { $0 == self })
|
delegatesReferences.removeAll(where: { $0 == self })
|
||||||
}
|
}
|
||||||
if let error = error as NSError? {
|
if let error = error as NSError? {
|
||||||
return promise.reject(error: .capture(.unknown(message: error.description)), cause: error)
|
promise.reject(error: .capture(.unknown(message: error.description)), cause: error)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Private
|
|
||||||
|
|
||||||
private let promise: Promise
|
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::String &v
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSArray* convertJSICStyleArrayToNSArray(jsi::Runtime &runtime, const jsi::Value* array, size_t length, std::shared_ptr<CallInvoker> jsInvoker) {
|
NSArray* convertJSICStyleArrayToNSArray(jsi::Runtime &runtime, const jsi::Value* array, size_t length, std::shared_ptr<CallInvoker> jsInvoker) {
|
||||||
if (length == 0) return @[];
|
if (length < 1) return @[];
|
||||||
NSMutableArray *result = [NSMutableArray new];
|
NSMutableArray *result = [NSMutableArray new];
|
||||||
for (size_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++) {
|
||||||
// Insert kCFNull when it's `undefined` value to preserve the indices.
|
// Insert kCFNull when it's `undefined` value to preserve the indices.
|
||||||
|
Loading…
Reference in New Issue
Block a user