diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 1ec29577175a..64b7cfd03f81 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Minor iOS internal code cleanup related to flash mode. + ## 0.9.4+8 * Fixes a bug where ImageFormatGroup was ignored in `startImageStream` on iOS. @@ -5,7 +9,7 @@ ## 0.9.4+7 * Fixes a crash in iOS when passing null queue pointer into AVFoundation API due to race condition. -* Minor iOS internal code cleanup. +* Minor iOS internal code cleanup related to dispatch queue. ## 0.9.4+6 diff --git a/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj index 80f672b5b9cf..87bcf2e666cd 100644 --- a/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; E01EE4A82799F3A5008C1950 /* QueueHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E01EE4A72799F3A5008C1950 /* QueueHelperTests.m */; }; E032F250279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */; }; + E032F2A727A0BF2D009E9028 /* FLTFlashModeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E032F2A627A0BF2D009E9028 /* FLTFlashModeTests.m */; }; E0C6E2002770F01A00EA6AA3 /* ThreadSafeMethodChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C6E1FD2770F01A00EA6AA3 /* ThreadSafeMethodChannelTests.m */; }; E0C6E2012770F01A00EA6AA3 /* ThreadSafeTextureRegistryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C6E1FE2770F01A00EA6AA3 /* ThreadSafeTextureRegistryTests.m */; }; E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C6E1FF2770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m */; }; @@ -81,6 +82,7 @@ A24F9E418BA48BCC7409B117 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; E01EE4A72799F3A5008C1950 /* QueueHelperTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QueueHelperTests.m; sourceTree = ""; }; E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraCaptureSessionQueueRaceConditionTests.m; sourceTree = ""; }; + E032F2A627A0BF2D009E9028 /* FLTFlashModeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLTFlashModeTests.m; sourceTree = ""; }; E0C6E1FD2770F01A00EA6AA3 /* ThreadSafeMethodChannelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadSafeMethodChannelTests.m; sourceTree = ""; }; E0C6E1FE2770F01A00EA6AA3 /* ThreadSafeTextureRegistryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadSafeTextureRegistryTests.m; sourceTree = ""; }; E0C6E1FF2770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadSafeEventChannelTests.m; sourceTree = ""; }; @@ -125,6 +127,7 @@ F6EE622E2710A6FC00905E4A /* MockFLTThreadSafeFlutterResult.m */, F63F9EED27143B19002479BF /* MockFLTThreadSafeFlutterResult.h */, E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */, + E032F2A627A0BF2D009E9028 /* FLTFlashModeTests.m */, ); path = RunnerTests; sourceTree = ""; @@ -388,6 +391,7 @@ buildActionMask = 2147483647; files = ( 03F6F8B226CBB4670024B8D3 /* ThreadSafeFlutterResultTests.m in Sources */, + E032F2A727A0BF2D009E9028 /* FLTFlashModeTests.m in Sources */, 033B94BE269C40A200B4DF97 /* CameraMethodChannelTests.m in Sources */, 03BB766B2665316900CE5A93 /* CameraFocusTests.m in Sources */, E487C86026D686A10034AC92 /* CameraPreviewPauseTests.m in Sources */, diff --git a/packages/camera/camera/example/ios/RunnerTests/FLTFlashModeTests.m b/packages/camera/camera/example/ios/RunnerTests/FLTFlashModeTests.m new file mode 100644 index 000000000000..b38b7eba8304 --- /dev/null +++ b/packages/camera/camera/example/ios/RunnerTests/FLTFlashModeTests.m @@ -0,0 +1,30 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@import camera.Test; +@import AVFoundation; +#import + +@interface FLTFlashModeTests : XCTestCase + +@end + +@implementation FLTFlashModeTests + +- (void)testFLTGetFLTFlashModeForString { + XCTAssertEqual(FLTFlashModeOff, FLTGetFLTFlashModeForString(@"off")); + XCTAssertEqual(FLTFlashModeAuto, FLTGetFLTFlashModeForString(@"auto")); + XCTAssertEqual(FLTFlashModeAlways, FLTGetFLTFlashModeForString(@"always")); + XCTAssertEqual(FLTFlashModeTorch, FLTGetFLTFlashModeForString(@"torch")); + XCTAssertThrows(FLTGetFLTFlashModeForString(@"unkwown")); +} + +- (void)testFLTGetAVCaptureFlashModeForFLTFlashMode { + XCTAssertEqual(AVCaptureFlashModeOff, FLTGetAVCaptureFlashModeForFLTFlashMode(FLTFlashModeOff)); + XCTAssertEqual(AVCaptureFlashModeAuto, FLTGetAVCaptureFlashModeForFLTFlashMode(FLTFlashModeAuto)); + XCTAssertEqual(AVCaptureFlashModeOn, FLTGetAVCaptureFlashModeForFLTFlashMode(FLTFlashModeAlways)); + XCTAssertEqual(-1, FLTGetAVCaptureFlashModeForFLTFlashMode(FLTFlashModeTorch)); +} + +@end diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.m b/packages/camera/camera/ios/Classes/CameraPlugin.m index e79a78348712..be5ba80923c2 100644 --- a/packages/camera/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera/ios/Classes/CameraPlugin.m @@ -14,6 +14,7 @@ #import "FLTThreadSafeFlutterResult.h" #import "FLTThreadSafeMethodChannel.h" #import "FLTThreadSafeTextureRegistry.h" +#import "FlashMode.h" @interface FLTSavePhotoDelegate : NSObject @property(readonly, nonatomic) NSString *path; @@ -113,34 +114,6 @@ - (void)captureOutput:(AVCapturePhotoOutput *)output } @end -// Mirrors FlashMode in flash_mode.dart -typedef enum { - FlashModeOff, - FlashModeAuto, - FlashModeAlways, - FlashModeTorch, -} FlashMode; - -static FlashMode getFlashModeForString(NSString *mode) { - if ([mode isEqualToString:@"off"]) { - return FlashModeOff; - } else if ([mode isEqualToString:@"auto"]) { - return FlashModeAuto; - } else if ([mode isEqualToString:@"always"]) { - return FlashModeAlways; - } else if ([mode isEqualToString:@"torch"]) { - return FlashModeTorch; - } else { - NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain - code:NSURLErrorUnknown - userInfo:@{ - NSLocalizedDescriptionKey : [NSString - stringWithFormat:@"Unknown flash mode %@", mode] - }]; - @throw error; - } -} - static OSType getVideoFormatFromString(NSString *videoFormatString) { if ([videoFormatString isEqualToString:@"bgra8888"]) { return kCVPixelFormatType_32BGRA; @@ -152,20 +125,6 @@ static OSType getVideoFormatFromString(NSString *videoFormatString) { } } -static AVCaptureFlashMode getAVCaptureFlashModeForFlashMode(FlashMode mode) { - switch (mode) { - case FlashModeOff: - return AVCaptureFlashModeOff; - case FlashModeAuto: - return AVCaptureFlashModeAuto; - case FlashModeAlways: - return AVCaptureFlashModeOn; - case FlashModeTorch: - default: - return -1; - } -} - // Mirrors ExposureMode in camera.dart typedef enum { ExposureModeAuto, @@ -349,7 +308,7 @@ @interface FLTCam : NSObject +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents camera's flash mode. Mirrors `FlashMode` enum in flash_mode.dart. + */ +typedef NS_ENUM(NSInteger, FLTFlashMode) { + FLTFlashModeOff, + FLTFlashModeAuto, + FLTFlashModeAlways, + FLTFlashModeTorch, +}; + +/** + * Gets FLTFlashMode from its string representation. + * @param mode a string representation of the FLTFlashMode. + */ +extern FLTFlashMode FLTGetFLTFlashModeForString(NSString *mode); + +/** + * Gets AVCaptureFlashMode from FLTFlashMode. + * @param mode flash mode. + */ +extern AVCaptureFlashMode FLTGetAVCaptureFlashModeForFLTFlashMode(FLTFlashMode mode); + +NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera/ios/Classes/FlashMode.m b/packages/camera/camera/ios/Classes/FlashMode.m new file mode 100644 index 000000000000..b9d4a4afd6bd --- /dev/null +++ b/packages/camera/camera/ios/Classes/FlashMode.m @@ -0,0 +1,39 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FlashMode.h" + +FLTFlashMode FLTGetFLTFlashModeForString(NSString *mode) { + if ([mode isEqualToString:@"off"]) { + return FLTFlashModeOff; + } else if ([mode isEqualToString:@"auto"]) { + return FLTFlashModeAuto; + } else if ([mode isEqualToString:@"always"]) { + return FLTFlashModeAlways; + } else if ([mode isEqualToString:@"torch"]) { + return FLTFlashModeTorch; + } else { + NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:NSURLErrorUnknown + userInfo:@{ + NSLocalizedDescriptionKey : [NSString + stringWithFormat:@"Unknown flash mode %@", mode] + }]; + @throw error; + } +} + +AVCaptureFlashMode FLTGetAVCaptureFlashModeForFLTFlashMode(FLTFlashMode mode) { + switch (mode) { + case FLTFlashModeOff: + return AVCaptureFlashModeOff; + case FLTFlashModeAuto: + return AVCaptureFlashModeAuto; + case FLTFlashModeAlways: + return AVCaptureFlashModeOn; + case FLTFlashModeTorch: + default: + return -1; + } +}