Skip to content

[camera_avfoundation] Implementation swift migration - part 7 #9595

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/camera/camera_avfoundation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.9.20+3

* Migrates `setZoomLevel` and `setFlashMode` methods to Swift.

## 0.9.20+2

* Migrates exposure offset and zoom factor limit getters to Swift.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ final class DefaultCamera: FLTCam, Camera {
private var exposureMode = FCPPlatformExposureMode.auto
private var focusMode = FCPPlatformFocusMode.auto

private static func flutterErrorFromNSError(_ error: NSError) -> FlutterError {
return FlutterError(
code: "Error \(error.code)",
message: error.localizedDescription,
details: error.domain)
}

func reportInitializationState() {
// Get all the state on the current thread, not the main thread.
let state = FCPPlatformCameraState.make(
Expand Down Expand Up @@ -241,6 +248,91 @@ final class DefaultCamera: FLTCam, Camera {
return CGPoint(x: x, y: y)
}

func setZoomLevel(_ zoom: CGFloat, withCompletion completion: @escaping (FlutterError?) -> Void) {
if zoom < captureDevice.minAvailableVideoZoomFactor
|| zoom > captureDevice.maxAvailableVideoZoomFactor
{
completion(
FlutterError(
code: "ZOOM_ERROR",
message:
"Zoom level out of bounds (zoom level should be between \(captureDevice.minAvailableVideoZoomFactor) and \(captureDevice.maxAvailableVideoZoomFactor).",
details: nil))
return
}

do {
try captureDevice.lockForConfiguration()
} catch let error as NSError {
completion(DefaultCamera.flutterErrorFromNSError(error))
return
}

captureDevice.videoZoomFactor = zoom
captureDevice.unlockForConfiguration()
completion(nil)
}

func setFlashMode(
_ mode: FCPPlatformFlashMode,
withCompletion completion: @escaping (FlutterError?) -> Void
) {
switch mode {
case .torch:
guard captureDevice.hasTorch else {
completion(
FlutterError(
code: "setFlashModeFailed",
message: "Device does not support torch mode",
details: nil)
)
return
}
guard captureDevice.isTorchAvailable else {
completion(
FlutterError(
code: "setFlashModeFailed",
message: "Torch mode is currently not available",
details: nil))
return
}
if captureDevice.torchMode != .on {
try? captureDevice.lockForConfiguration()
captureDevice.torchMode = .on
captureDevice.unlockForConfiguration()
}
case .off, .auto, .always:
guard captureDevice.hasFlash else {
completion(
FlutterError(
code: "setFlashModeFailed",
message: "Device does not have flash capabilities",
details: nil))
return
}
let avFlashMode = FCPGetAVCaptureFlashModeForPigeonFlashMode(mode)
guard capturePhotoOutput.supportedFlashModes.contains(NSNumber(value: avFlashMode.rawValue))
else {
completion(
FlutterError(
code: "setFlashModeFailed",
message: "Device does not support this specific flash mode",
details: nil))
return
}
if captureDevice.torchMode != .off {
try? captureDevice.lockForConfiguration()
captureDevice.torchMode = .off
captureDevice.unlockForConfiguration()
}
@unknown default:
assertionFailure("Unknown flash mode")
}

flashMode = mode
completion(nil)
}

func pausePreview() {
isPreviewPaused = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ @interface FLTCam () <AVCaptureVideoDataOutputSampleBufferDelegate,
@property(nonatomic, copy) CaptureDeviceFactory captureDeviceFactory;
@property(nonatomic, copy) AudioCaptureDeviceFactory audioCaptureDeviceFactory;
@property(readonly, nonatomic) NSObject<FLTCaptureDeviceInputFactory> *captureDeviceInputFactory;
@property(assign, nonatomic) FCPPlatformFlashMode flashMode;
@property(nonatomic, copy) AssetWriterFactory assetWriterFactory;
@property(nonatomic, copy) InputPixelBufferAdaptorFactory inputPixelBufferAdaptorFactory;
/// Reports the given error message to the Dart side of the plugin.
Expand Down Expand Up @@ -511,51 +510,6 @@ - (void)stopVideoRecordingWithCompletion:(void (^)(NSString *_Nullable,
}
}

- (void)setFlashMode:(FCPPlatformFlashMode)mode
withCompletion:(void (^)(FlutterError *_Nullable))completion {
if (mode == FCPPlatformFlashModeTorch) {
if (!_captureDevice.hasTorch) {
completion([FlutterError errorWithCode:@"setFlashModeFailed"
message:@"Device does not support torch mode"
details:nil]);
return;
}
if (!_captureDevice.isTorchAvailable) {
completion([FlutterError errorWithCode:@"setFlashModeFailed"
message:@"Torch mode is currently not available"
details:nil]);
return;
}
if (_captureDevice.torchMode != AVCaptureTorchModeOn) {
[_captureDevice lockForConfiguration:nil];
[_captureDevice setTorchMode:AVCaptureTorchModeOn];
[_captureDevice unlockForConfiguration];
}
} else {
if (!_captureDevice.hasFlash) {
completion([FlutterError errorWithCode:@"setFlashModeFailed"
message:@"Device does not have flash capabilities"
details:nil]);
return;
}
AVCaptureFlashMode avFlashMode = FCPGetAVCaptureFlashModeForPigeonFlashMode(mode);
if (![_capturePhotoOutput.supportedFlashModes
containsObject:[NSNumber numberWithInt:((int)avFlashMode)]]) {
completion([FlutterError errorWithCode:@"setFlashModeFailed"
message:@"Device does not support this specific flash mode"
details:nil]);
return;
}
if (_captureDevice.torchMode != AVCaptureTorchModeOff) {
[_captureDevice lockForConfiguration:nil];
[_captureDevice setTorchMode:AVCaptureTorchModeOff];
[_captureDevice unlockForConfiguration];
}
}
_flashMode = mode;
completion(nil);
}

- (void)setDescriptionWhileRecording:(NSString *)cameraName
withCompletion:(void (^)(FlutterError *_Nullable))completion {
if (!_isRecording) {
Expand Down Expand Up @@ -667,29 +621,6 @@ - (void)stopImageStream {
}
}

- (void)setZoomLevel:(CGFloat)zoom withCompletion:(void (^)(FlutterError *_Nullable))completion {
if (_captureDevice.maxAvailableVideoZoomFactor < zoom ||
_captureDevice.minAvailableVideoZoomFactor > zoom) {
NSString *errorMessage = [NSString
stringWithFormat:@"Zoom level out of bounds (zoom level should be between %f and %f).",
_captureDevice.minAvailableVideoZoomFactor,
_captureDevice.maxAvailableVideoZoomFactor];

completion([FlutterError errorWithCode:@"ZOOM_ERROR" message:errorMessage details:nil]);
return;
}

NSError *error = nil;
if (![_captureDevice lockForConfiguration:&error]) {
completion(FlutterErrorFromNSError(error));
return;
}
_captureDevice.videoZoomFactor = zoom;
[_captureDevice unlockForConfiguration];

completion(nil);
}

- (BOOL)setupWriterForPath:(NSString *)path {
NSError *error = nil;
NSURL *outputURL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
@property(readonly, nonatomic) NSObject<FLTDeviceOrientationProviding> *deviceOrientationProvider;
@property(assign, nonatomic) UIDeviceOrientation lockedCaptureOrientation;
@property(assign, nonatomic) UIDeviceOrientation deviceOrientation;
@property(assign, nonatomic) FCPPlatformFlashMode flashMode;

/// Initializes an `FLTCam` instance with the given configuration.
/// @param error report to the caller if any error happened creating the camera.
Expand All @@ -66,16 +67,13 @@ NS_ASSUME_NONNULL_BEGIN
messengerForStreaming:(nullable NSObject<FlutterBinaryMessenger> *)messenger;
- (void)stopVideoRecordingWithCompletion:(void (^)(NSString *_Nullable,
FlutterError *_Nullable))completion;
- (void)setFlashMode:(FCPPlatformFlashMode)mode
withCompletion:(void (^)(FlutterError *_Nullable))completion;

- (void)setDescriptionWhileRecording:(NSString *)cameraName
withCompletion:(void (^)(FlutterError *_Nullable))completion;

- (void)startImageStreamWithMessenger:(NSObject<FlutterBinaryMessenger> *)messenger
completion:(nonnull void (^)(FlutterError *_Nullable))completion;
- (void)stopImageStream;
- (void)setZoomLevel:(CGFloat)zoom withCompletion:(void (^)(FlutterError *_Nullable))completion;
- (void)setUpCaptureSessionForAudioIfNeeded;

// Methods exposed for the Swift DefaultCamera subclass
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera_avfoundation/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: camera_avfoundation
description: iOS implementation of the camera plugin.
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
version: 0.9.20+2
version: 0.9.20+3

environment:
sdk: ^3.6.0
Expand Down