From 1185f80b520954e49b46487a9ed777545de433f5 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Fri, 27 Dec 2024 14:07:32 +0100 Subject: [PATCH 01/16] Introduce protocols and remove OCMock from CameraFocusTests --- .../ios/Runner.xcodeproj/project.pbxproj | 81 ++++++--- .../xcshareddata/swiftpm/Package.resolved | 14 ++ .../ios/RunnerTests/CameraFocusTests.m | 135 ++++++++------ .../ios/RunnerTests/CameraPreviewPauseTests.m | 1 - .../example/ios/RunnerTests/CameraTestUtils.m | 9 +- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 7 +- .../RunnerTests/MockCaptureDeviceController.h | 80 +++++++++ .../RunnerTests/MockCaptureDeviceController.m | 127 +++++++++++++ .../MockDeviceOrientationProvider.h | 17 ++ .../MockDeviceOrientationProvider.m | 14 ++ .../RunnerTests/Mocks/MockDeviceController.m | 6 + .../Sources/camera_avfoundation/FLTCam.m | 21 ++- .../FLTCamMediaSettingsAVWrapper.m | 9 +- .../Protocols/FLTCaptureDeviceControlling.m | 170 ++++++++++++++++++ .../Protocols/FLTDeviceOrientationProviding.m | 13 ++ .../include/CameraPlugin.modulemap | 2 + .../include/camera_avfoundation/FLTCam.h | 5 +- .../FLTCamMediaSettingsAVWrapper.h | 10 +- .../include/camera_avfoundation/FLTCam_Test.h | 3 +- .../Protocols/FLTCaptureDeviceControlling.h | 72 ++++++++ .../Protocols/FLTDeviceOrientationProviding.h | 17 ++ 21 files changed, 709 insertions(+), 104 deletions(-) create mode 100644 packages/camera/camera_avfoundation/example/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h create mode 100644 packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m create mode 100644 packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.h create mode 100644 packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.m create mode 100644 packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockDeviceController.m create mode 100644 packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m create mode 100644 packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m create mode 100644 packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h create mode 100644 packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h diff --git a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj index 041d918da5b9..04b0b3c45500 100644 --- a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,22 +3,25 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ 033B94BE269C40A200B4DF97 /* CameraMethodChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 033B94BD269C40A200B4DF97 /* CameraMethodChannelTests.m */; }; 03BB766B2665316900CE5A93 /* CameraFocusTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 03BB766A2665316900CE5A93 /* CameraFocusTests.m */; }; + 1000364CB781922C6D6AAA4A /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DDC4CE84A8B378AE4A8CD9C /* libPods-RunnerTests.a */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 236906D1621AE863A5B2E770 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 89D82918721FABF772705DB0 /* libPods-Runner.a */; }; - 25C3919135C3D981E6F800D0 /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1944D8072499F3B5E7653D44 /* libPods-RunnerTests.a */; }; 334733EA2668111C00DCC49E /* CameraOrientationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 03BB767226653ABE00CE5A93 /* CameraOrientationTests.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 408D7A792C3C9CD000B71F9A /* OCMock in Frameworks */ = {isa = PBXBuildFile; productRef = 408D7A782C3C9CD000B71F9A /* OCMock */; }; 43ED1537282570DE00EB00DE /* AvailableCamerasTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 43ED1536282570DE00EB00DE /* AvailableCamerasTest.m */; }; + 54D650172516862D30686934 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ECAF63F924EFA2D68883BA85 /* libPods-Runner.a */; }; 788A065A27B0E02900533D74 /* StreamingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 788A065927B0E02900533D74 /* StreamingTest.m */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 7D5FCCD42AEF9D0200FB7108 /* CameraSettingsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D5FCCD32AEF9D0200FB7108 /* CameraSettingsTests.m */; }; + 7F56D0382D1EDDCE005676A5 /* CameraPermissionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */; }; + 7F87E8022D01FD6F00A3549C /* MockCaptureDeviceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F87E8012D01FD5600A3549C /* MockCaptureDeviceController.m */; }; + 7F87E80C2D0325D900A3549C /* MockDeviceOrientationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F87E80B2D0325D700A3549C /* MockDeviceOrientationProvider.m */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -30,7 +33,6 @@ E04F108627A87CA600573D0C /* FLTSavePhotoDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E04F108527A87CA600573D0C /* FLTSavePhotoDelegateTests.m */; }; E071CF7227B3061B006EF3BA /* FLTCamPhotoCaptureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E071CF7127B3061B006EF3BA /* FLTCamPhotoCaptureTests.m */; }; E071CF7427B31DE4006EF3BA /* FLTCamSampleBufferTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E071CF7327B31DE4006EF3BA /* FLTCamSampleBufferTests.m */; }; - E0B0D2BB27DFF2AF00E71E4B /* CameraPermissionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */; }; E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C6E1FF2770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m */; }; E0CDBAC227CD9729002561D9 /* CameraTestUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E0CDBAC127CD9729002561D9 /* CameraTestUtils.m */; }; E0F95E3D27A32AB900699390 /* CameraPropertiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0F95E3C27A32AB900699390 /* CameraPropertiesTests.m */; }; @@ -68,17 +70,18 @@ 03BB767226653ABE00CE5A93 /* CameraOrientationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraOrientationTests.m; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 14AE82C910C2A12F2ECB2094 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 1944D8072499F3B5E7653D44 /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 43ED1536282570DE00EB00DE /* AvailableCamerasTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AvailableCamerasTest.m; sourceTree = ""; }; - 59848A7CA98C1FADF8840207 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 4A191381C3593DF1AC4E7559 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 788A065927B0E02900533D74 /* StreamingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StreamingTest.m; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 7D5FCCD32AEF9D0200FB7108 /* CameraSettingsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraSettingsTests.m; sourceTree = ""; }; - 89D82918721FABF772705DB0 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 7F87E8012D01FD5600A3549C /* MockCaptureDeviceController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCaptureDeviceController.m; sourceTree = ""; }; + 7F87E8032D02FF8C00A3549C /* MockCaptureDeviceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCaptureDeviceController.h; sourceTree = ""; }; + 7F87E80A2D0325B200A3549C /* MockDeviceOrientationProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockDeviceOrientationProvider.h; sourceTree = ""; }; + 7F87E80B2D0325D700A3549C /* MockDeviceOrientationProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockDeviceOrientationProvider.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -87,8 +90,9 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9C5CC6CAD53AD388B2694F3A /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 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 = ""; }; + 9DDC4CE84A8B378AE4A8CD9C /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + A8F314CD1C64E9257EBC811D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + B61D98BBC8FB276D1C4A7BB2 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; CEF661192B5E36A500D33FD4 /* CameraSessionPresetsTests.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = CameraSessionPresetsTests.m; sourceTree = ""; }; E01EE4A72799F3A5008C1950 /* QueueUtilsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QueueUtilsTests.m; sourceTree = ""; }; E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraCaptureSessionQueueRaceConditionTests.m; sourceTree = ""; }; @@ -101,6 +105,8 @@ E0CDBAC127CD9729002561D9 /* CameraTestUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraTestUtils.m; sourceTree = ""; }; E0F95E3C27A32AB900699390 /* CameraPropertiesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraPropertiesTests.m; sourceTree = ""; }; E487C85F26D686A10034AC92 /* CameraPreviewPauseTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraPreviewPauseTests.m; sourceTree = ""; }; + E67C6DBF6478BE708993169F /* 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 = ""; }; + ECAF63F924EFA2D68883BA85 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -109,7 +115,7 @@ buildActionMask = 2147483647; files = ( 408D7A792C3C9CD000B71F9A /* OCMock in Frameworks */, - 25C3919135C3D981E6F800D0 /* libPods-RunnerTests.a in Frameworks */, + 1000364CB781922C6D6AAA4A /* libPods-RunnerTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -118,7 +124,7 @@ buildActionMask = 2147483647; files = ( 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, - 236906D1621AE863A5B2E770 /* libPods-Runner.a in Frameworks */, + 54D650172516862D30686934 /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -128,6 +134,10 @@ 03BB76692665316900CE5A93 /* RunnerTests */ = { isa = PBXGroup; children = ( + 7F87E80B2D0325D700A3549C /* MockDeviceOrientationProvider.m */, + 7F87E80A2D0325B200A3549C /* MockDeviceOrientationProvider.h */, + 7F87E8032D02FF8C00A3549C /* MockCaptureDeviceController.h */, + 7F87E8012D01FD5600A3549C /* MockCaptureDeviceController.m */, 7D5FCCD32AEF9D0200FB7108 /* CameraSettingsTests.m */, 03BB766A2665316900CE5A93 /* CameraFocusTests.m */, 03BB767226653ABE00CE5A93 /* CameraOrientationTests.m */, @@ -154,8 +164,8 @@ 3242FD2B467C15C62200632F /* Frameworks */ = { isa = PBXGroup; children = ( - 89D82918721FABF772705DB0 /* libPods-Runner.a */, - 1944D8072499F3B5E7653D44 /* libPods-RunnerTests.a */, + ECAF63F924EFA2D68883BA85 /* libPods-Runner.a */, + 9DDC4CE84A8B378AE4A8CD9C /* libPods-RunnerTests.a */, ); name = Frameworks; sourceTree = ""; @@ -219,10 +229,10 @@ FD386F00E98D73419C929072 /* Pods */ = { isa = PBXGroup; children = ( - 59848A7CA98C1FADF8840207 /* Pods-Runner.debug.xcconfig */, - 14AE82C910C2A12F2ECB2094 /* Pods-Runner.release.xcconfig */, - 9C5CC6CAD53AD388B2694F3A /* Pods-RunnerTests.debug.xcconfig */, - A24F9E418BA48BCC7409B117 /* Pods-RunnerTests.release.xcconfig */, + A8F314CD1C64E9257EBC811D /* Pods-Runner.debug.xcconfig */, + 4A191381C3593DF1AC4E7559 /* Pods-Runner.release.xcconfig */, + B61D98BBC8FB276D1C4A7BB2 /* Pods-RunnerTests.debug.xcconfig */, + E67C6DBF6478BE708993169F /* Pods-RunnerTests.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -263,6 +273,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 2B62C73988DE02487EF557D4 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -305,7 +316,7 @@ ); mainGroup = 97C146E51CF9000F007C117D; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, 408D7A772C3C9CD000B71F9A /* XCRemoteSwiftPackageReference "ocmock" */, ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; @@ -340,6 +351,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 2B62C73988DE02487EF557D4 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/camera_avfoundation/camera_avfoundation_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation/path_provider_foundation_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/video_player_avfoundation/video_player_avfoundation_privacy.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/camera_avfoundation_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/path_provider_foundation_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/video_player_avfoundation_privacy.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -424,10 +457,13 @@ files = ( 033B94BE269C40A200B4DF97 /* CameraMethodChannelTests.m in Sources */, E071CF7227B3061B006EF3BA /* FLTCamPhotoCaptureTests.m in Sources */, + 7F56D0382D1EDDCE005676A5 /* CameraPermissionTests.m in Sources */, E0F95E3D27A32AB900699390 /* CameraPropertiesTests.m in Sources */, 03BB766B2665316900CE5A93 /* CameraFocusTests.m in Sources */, + 7F87E8022D01FD6F00A3549C /* MockCaptureDeviceController.m in Sources */, 7D5FCCD42AEF9D0200FB7108 /* CameraSettingsTests.m in Sources */, E487C86026D686A10034AC92 /* CameraPreviewPauseTests.m in Sources */, + 7F87E80C2D0325D900A3549C /* MockDeviceOrientationProvider.m in Sources */, E071CF7427B31DE4006EF3BA /* FLTCamSampleBufferTests.m in Sources */, E04F108627A87CA600573D0C /* FLTSavePhotoDelegateTests.m in Sources */, 43ED1537282570DE00EB00DE /* AvailableCamerasTest.m in Sources */, @@ -437,7 +473,6 @@ E032F250279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m in Sources */, 788A065A27B0E02900533D74 /* StreamingTest.m in Sources */, E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */, - E0B0D2BB27DFF2AF00E71E4B /* CameraPermissionTests.m in Sources */, E01EE4A82799F3A5008C1950 /* QueueUtilsTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -484,7 +519,7 @@ /* Begin XCBuildConfiguration section */ 03BB766F2665316900CE5A93 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9C5CC6CAD53AD388B2694F3A /* Pods-RunnerTests.debug.xcconfig */; + baseConfigurationReference = B61D98BBC8FB276D1C4A7BB2 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -513,7 +548,7 @@ }; 03BB76702665316900CE5A93 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A24F9E418BA48BCC7409B117 /* Pods-RunnerTests.release.xcconfig */; + baseConfigurationReference = E67C6DBF6478BE708993169F /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -726,7 +761,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/packages/camera/camera_avfoundation/example/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/packages/camera/camera_avfoundation/example/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000000..a8d31f4703ec --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,14 @@ +{ + "originHash" : "20e8ffe6c32a926c4f00e4e9a967104dab3f8007aacc282029f03ed5f5f2e183", + "pins" : [ + { + "identity" : "ocmock", + "kind" : "remoteSourceControl", + "location" : "https://github.com/erikdoe/ocmock", + "state" : { + "revision" : "fe1661a3efed11831a6452f4b1a0c5e6ddc08c3d" + } + } + ], + "version" : 3 +} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m index 0cb8333345ab..edcd7c4795c7 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m @@ -8,120 +8,149 @@ #endif @import XCTest; @import AVFoundation; -#import + +#import "MockCaptureDeviceController.h" +#import "MockDeviceOrientationProvider.h" @interface CameraFocusTests : XCTestCase @property(readonly, nonatomic) FLTCam *camera; -@property(readonly, nonatomic) id mockDevice; -@property(readonly, nonatomic) id mockUIDevice; +@property(readonly, nonatomic) MockCaptureDeviceController *mockDevice; +@property(readonly, nonatomic) MockDeviceOrientationProvider *mockDeviceOrientationProvider; @end @implementation CameraFocusTests - (void)setUp { _camera = [[FLTCam alloc] init]; - _mockDevice = OCMClassMock([AVCaptureDevice class]); - _mockUIDevice = OCMPartialMock([UIDevice currentDevice]); -} - -- (void)tearDown { - [_mockDevice stopMocking]; - [_mockUIDevice stopMocking]; + _mockDevice = [[MockCaptureDeviceController alloc] init]; + _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; } - (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus { - // AVCaptureFocusModeContinuousAutoFocus is supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true); - // AVCaptureFocusModeContinuousAutoFocus is supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true); - - // Don't expect setFocusMode:AVCaptureFocusModeAutoFocus - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus]; + // AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeContinuousAutoFocus are supported + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { + return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus; + }; + + __block BOOL setFocusModeContinuousAutoFocusCalled = NO; + + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { + // Don't expect setFocusMode:AVCaptureFocusModeAutoFocus + if (mode == AVCaptureFocusModeAutoFocus) { + XCTFail(@"Unexpected call to setFocusMode"); + } else if (mode == AVCaptureFocusModeContinuousAutoFocus) { + setFocusModeContinuousAutoFocusCalled = YES; + } + }; // Run test [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; // Expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus - OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus]); + XCTAssertTrue(setFocusModeContinuousAutoFocusCalled); } - (void)testAutoFocusWithContinuousModeNotSupported_ShouldSetAutoFocus { // AVCaptureFocusModeContinuousAutoFocus is not supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) - .andReturn(false); - // AVCaptureFocusModeContinuousAutoFocus is supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true); - + // AVCaptureFocusModeAutoFocus is supported + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { + return mode == AVCaptureFocusModeAutoFocus; + }; + + __block BOOL setFocusModeAutoFocusCalled = NO; + // Don't expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; - + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { + if (mode == AVCaptureFocusModeContinuousAutoFocus) { + XCTFail(@"Unexpected call to setFocusMode"); + } else if (mode == AVCaptureFocusModeAutoFocus) { + setFocusModeAutoFocusCalled = YES; + } + }; + // Run test [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; - + // Expect setFocusMode:AVCaptureFocusModeAutoFocus - OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeAutoFocus]); + XCTAssertTrue(setFocusModeAutoFocusCalled); } - (void)testAutoFocusWithNoModeSupported_ShouldSetNothing { - // AVCaptureFocusModeContinuousAutoFocus is not supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) - .andReturn(false); - // AVCaptureFocusModeContinuousAutoFocus is not supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(false); + // No modes are supported + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { + return NO; + }; // Don't expect any setFocus - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus]; + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { + XCTFail(@"Unexpected call to setFocusMode"); + }; // Run test [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; } - (void)testLockedFocusWithModeSupported_ShouldSetModeAutoFocus { - // AVCaptureFocusModeContinuousAutoFocus is supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true); - // AVCaptureFocusModeContinuousAutoFocus is supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true); - - // Don't expect any setFocus - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; - + // AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeAutoFocus are supported + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { + return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus; + }; + + __block BOOL setFocusModeAutoFocusCalled = NO; + + // Expect only setFocusMode:AVCaptureFocusModeAutoFocus + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { + if (mode == AVCaptureFocusModeContinuousAutoFocus) { + XCTFail(@"Unexpected call to setFocusMode"); + } else if (mode == AVCaptureFocusModeAutoFocus) { + setFocusModeAutoFocusCalled = YES; + } + }; + // Run test [_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice]; - // Expect setFocusMode:AVCaptureFocusModeAutoFocus - OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeAutoFocus]); + XCTAssertTrue(setFocusModeAutoFocusCalled); } - (void)testLockedFocusWithModeNotSupported_ShouldSetNothing { - // AVCaptureFocusModeContinuousAutoFocus is supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true); - // AVCaptureFocusModeContinuousAutoFocus is not supported - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(false); + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { + return mode == AVCaptureFocusModeContinuousAutoFocus; + }; // Don't expect any setFocus - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus]; + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { + XCTFail(@"Unexpected call to setFocusMode"); + }; // Run test [_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice]; } +// TODO(mchudy): replace setValue with proper DI - (void)testSetFocusPointWithResult_SetsFocusPointOfInterest { // UI is currently in landscape left orientation - OCMStub([(UIDevice *)_mockUIDevice orientation]).andReturn(UIDeviceOrientationLandscapeLeft); + [_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"]; + _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Focus point of interest is supported - OCMStub([_mockDevice isFocusPointOfInterestSupported]).andReturn(true); + _mockDevice.isFocusPointOfInterestSupported = YES; // Set mock device as the current capture device [_camera setValue:_mockDevice forKey:@"captureDevice"]; + __block BOOL setFocusPointOfInterestCalled = NO; + _mockDevice.setFocusPointOfInterestStub = ^(CGPoint point) { + if (point.x == 1 && point.y == 1) { + setFocusPointOfInterestCalled = YES; + } + }; + // Run test [_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1] withCompletion:^(FlutterError *_Nullable error){ }]; // Verify the focus point of interest has been set - OCMVerify([_mockDevice setFocusPointOfInterest:CGPointMake(1, 1)]); + XCTAssertTrue(setFocusPointOfInterestCalled); } @end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.m index 04bdd0795dab..60dfca541683 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.m @@ -8,7 +8,6 @@ #endif @import XCTest; @import AVFoundation; -#import @interface CameraPreviewPauseTests : XCTestCase @end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m index 503a5c255c59..501498d6382b 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m @@ -88,8 +88,8 @@ videoCaptureSession:videoSessionMock audioCaptureSession:audioSessionMock captureSessionQueue:captureSessionQueue - captureDeviceFactory:captureDeviceFactory ?: ^AVCaptureDevice *(void) { - return captureDeviceMock; + captureDeviceFactory:captureDeviceFactory ?: ^id(void) { + return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDeviceMock]; } videoDimensionsForFormat:^CMVideoDimensions(AVCaptureDeviceFormat *format) { return CMVideoFormatDescriptionGetDimensions(format.formatDescription); @@ -161,9 +161,8 @@ videoCaptureSession:captureSession audioCaptureSession:audioSessionMock captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL) - captureDeviceFactory:^AVCaptureDevice *(void) { - return captureDevice; - } + captureDeviceFactory:^id(void) { + return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDevice]; } videoDimensionsForFormat:videoDimensionsForFormat error:nil]; } diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 7f17e39a6b0b..31711f065efd 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -171,7 +171,7 @@ - (void)testCaptureToFile_mustReportFileExtensionWithJpgWhenHEVCNotAvailableAndF }); [self waitForExpectationsWithTimeout:1 handler:nil]; } - +// - (void)testCaptureToFile_handlesTorchMode { XCTestExpectation *pathExpectation = [self expectationWithDescription: @@ -188,8 +188,9 @@ - (void)testCaptureToFile_handlesTorchMode { (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(captureSessionQueue, nil, nil, - ^AVCaptureDevice *(void) { - return captureDeviceMock; + ^id(void) { + return + [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDeviceMock]; }); AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h new file mode 100644 index 000000000000..8723b1910244 --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h @@ -0,0 +1,80 @@ +// 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_avfoundation; +#if __has_include() +@import camera_avfoundation.Test; +#endif +@import AVFoundation; + +NS_ASSUME_NONNULL_BEGIN + +@interface MockCaptureDeviceController : NSObject +// Position/Orientation +@property(nonatomic, assign) AVCaptureDevicePosition position; + +// Format/Configuration +@property(nonatomic, strong) AVCaptureDeviceFormat *activeFormat; +@property(nonatomic, strong) NSArray *formats; +@property(nonatomic, copy) void (^setActiveFormatStub)(AVCaptureDeviceFormat *format); + +// Flash/Torch +@property(nonatomic, assign) BOOL hasFlash; +@property(nonatomic, assign) BOOL hasTorch; +@property(nonatomic, assign) BOOL isTorchAvailable; +@property(nonatomic, assign) AVCaptureTorchMode torchMode; +@property(nonatomic, copy) void (^setTorchModeStub)(AVCaptureTorchMode mode); +@property(nonatomic, assign) BOOL flashModeSupported; + +// Focus +@property(nonatomic, assign) BOOL focusPointOfInterestSupported; +@property(nonatomic, copy) BOOL (^isFocusModeSupportedStub)(AVCaptureFocusMode mode); +@property(nonatomic, assign) AVCaptureFocusMode focusMode; +@property(nonatomic, copy) void (^setFocusModeStub)(AVCaptureFocusMode mode); +@property(nonatomic, assign) CGPoint focusPointOfInterest; +@property(nonatomic, copy) void (^setFocusPointOfInterestStub)(CGPoint point); + +// Exposure +@property(nonatomic, assign) BOOL exposurePointOfInterestSupported; +@property(nonatomic, assign) AVCaptureExposureMode exposureMode; +@property(nonatomic, assign) BOOL exposureModeSupported; +@property(nonatomic, copy) void (^setExposureModeStub)(AVCaptureExposureMode mode); +@property(nonatomic, assign) CGPoint exposurePointOfInterest; +@property(nonatomic, copy) void (^setExposurePointOfInterestStub)(CGPoint point); +@property(nonatomic, assign) float minExposureTargetBias; +@property(nonatomic, assign) float maxExposureTargetBias; +@property(nonatomic, copy) void (^setExposureTargetBiasStub)(float bias, void (^_Nullable handler)(CMTime)); + +// Zoom +@property(nonatomic, assign) float maxAvailableVideoZoomFactor; +@property(nonatomic, assign) float minAvailableVideoZoomFactor; +@property(nonatomic, assign) float videoZoomFactor; +@property(nonatomic, copy) void (^setVideoZoomFactorStub)(float factor); + +// Camera Properties +@property(nonatomic, assign) float lensAperture; +@property(nonatomic, assign) CMTime exposureDuration; +@property(nonatomic, assign) float ISO; + +// Configuration Lock +@property(nonatomic, assign) BOOL shouldFailConfiguration; +@property(nonatomic, copy) void (^lockForConfigurationStub)(NSError **error); +@property(nonatomic, copy) void (^unlockForConfigurationStub)(void); + +// Frame Duration +@property(nonatomic, assign) CMTime activeVideoMinFrameDuration; +@property(nonatomic, assign) CMTime activeVideoMaxFrameDuration; +@property(nonatomic, copy) void (^setActiveVideoMinFrameDurationStub)(CMTime duration); +@property(nonatomic, copy) void (^setActiveVideoMaxFrameDurationStub)(CMTime duration); + +// Input Creation +@property(nonatomic, strong) AVCaptureInput *inputToReturn; +@property(nonatomic, copy) void (^createInputStub)(NSError **error); + +@property(nonatomic, assign) BOOL isExposurePointOfInterestSupported; +@property(nonatomic, assign) BOOL isFocusPointOfInterestSupported; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m new file mode 100644 index 000000000000..c1659d36f07d --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m @@ -0,0 +1,127 @@ +// 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_avfoundation; +#if __has_include() +@import camera_avfoundation.Test; +#endif +@import AVFoundation; + +#import "MockCaptureDeviceController.h" + +@implementation MockCaptureDeviceController + +- (void)setActiveFormat:(AVCaptureDeviceFormat *)format { + _activeFormat = format; + if (self.setActiveFormatStub) { + self.setActiveFormatStub(format); + } +} + +- (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode { + return self.flashModeSupported; +} + +- (void)setTorchMode:(AVCaptureTorchMode)mode { + _torchMode = mode; + if (self.setTorchModeStub) { + self.setTorchModeStub(mode); + } +} + +- (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode { + if (self.isFocusModeSupportedStub) { + return self.isFocusModeSupportedStub(mode); + } + return NO; +} + +- (void)setFocusMode:(AVCaptureFocusMode)mode { + _focusMode = mode; + if (self.setFocusModeStub) { + self.setFocusModeStub(mode); + } +} + +- (void)setFocusPointOfInterest:(CGPoint)point { + _focusPointOfInterest = point; + if (self.setFocusPointOfInterestStub) { + self.setFocusPointOfInterestStub(point); + } +} + +- (void)setExposureMode:(AVCaptureExposureMode)mode { + _exposureMode = mode; + if (self.setExposureModeStub) { + self.setExposureModeStub(mode); + } +} + +- (void)setExposurePointOfInterest:(CGPoint)point { + _exposurePointOfInterest = point; + if (self.setExposurePointOfInterestStub) { + self.setExposurePointOfInterestStub(point); + } +} + +- (void)setExposureTargetBias:(float)bias completionHandler:(void (^)(CMTime))handler { + if (self.setExposureTargetBiasStub) { + self.setExposureTargetBiasStub(bias, handler); + } +} + +- (void)setVideoZoomFactor:(float)factor { + _videoZoomFactor = factor; + if (self.setVideoZoomFactorStub) { + self.setVideoZoomFactorStub(factor); + } +} + +- (BOOL)lockForConfiguration:(NSError **)error { + if (self.lockForConfigurationStub) { + self.lockForConfigurationStub(error); + return !self.shouldFailConfiguration; + } + if (self.shouldFailConfiguration) { + if (error) { + *error = [NSError errorWithDomain:@"test" code:0 userInfo:nil]; + } + return NO; + } + return YES; +} + +- (void)unlockForConfiguration { + if (self.unlockForConfigurationStub) { + self.unlockForConfigurationStub(); + } +} + +- (void)setActiveVideoMinFrameDuration:(CMTime)duration { + _activeVideoMinFrameDuration = duration; + if (self.setActiveVideoMinFrameDurationStub) { + self.setActiveVideoMinFrameDurationStub(duration); + } +} + +- (void)setActiveVideoMaxFrameDuration:(CMTime)duration { + _activeVideoMaxFrameDuration = duration; + if (self.setActiveVideoMaxFrameDurationStub) { + self.setActiveVideoMaxFrameDurationStub(duration); + } +} + +- (BOOL)isExposureModeSupported:(AVCaptureExposureMode)mode { + return self.exposureModeSupported; +} + +- (AVCaptureInput *)createInput:(NSError *_Nullable *_Nullable)error { + if (self.createInputStub) { + self.createInputStub(error); + } + return self.inputToReturn; +} + + +@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.h new file mode 100644 index 000000000000..0421ec665293 --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.h @@ -0,0 +1,17 @@ +// 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_avfoundation; +#if __has_include() +@import camera_avfoundation.Test; +#endif +@import AVFoundation; + +NS_ASSUME_NONNULL_BEGIN + +@interface MockDeviceOrientationProvider : NSObject +@property(nonatomic, assign) UIDeviceOrientation orientation; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.m new file mode 100644 index 000000000000..963cb7e96ff9 --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.m @@ -0,0 +1,14 @@ +// 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_avfoundation; +#if __has_include() +@import camera_avfoundation.Test; +#endif +@import AVFoundation; + +#import "MockDeviceOrientationProvider.h" + +@implementation MockDeviceOrientationProvider +@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockDeviceController.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockDeviceController.m new file mode 100644 index 000000000000..27cc985d7d2b --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockDeviceController.m @@ -0,0 +1,6 @@ +// 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. + + +@interface FLTMockCaptureDeviceController : NSObject diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m index 699dbf3a806e..beb2c2ad6329 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m @@ -13,6 +13,8 @@ #import "./include/camera_avfoundation/FLTThreadSafeEventChannel.h" #import "./include/camera_avfoundation/QueueUtils.h" #import "./include/camera_avfoundation/messages.g.h" +#import "./include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h" +#import "./include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h" static FlutterError *FlutterErrorFromNSError(NSError *error) { return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %d", (int)error.code] @@ -103,7 +105,7 @@ @interface FLTCam () deviceOrientationProvider; /// Reports the given error message to the Dart side of the plugin. /// /// Can be called from any thread. @@ -144,8 +146,9 @@ - (instancetype)initWithCameraName:(NSString *)cameraName videoCaptureSession:videoCaptureSession audioCaptureSession:videoCaptureSession captureSessionQueue:captureSessionQueue - captureDeviceFactory:^AVCaptureDevice *(void) { - return [AVCaptureDevice deviceWithUniqueID:cameraName]; + captureDeviceFactory:^id (void) { + AVCaptureDevice *device = [AVCaptureDevice deviceWithUniqueID:cameraName]; + return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:device]; } videoDimensionsForFormat:^CMVideoDimensions(AVCaptureDeviceFormat *format) { return CMVideoFormatDescriptionGetDimensions(format.formatDescription); @@ -264,6 +267,8 @@ - (instancetype)initWithMediaSettings:(FCPPlatformMediaSettings *)mediaSettings _motionManager = [[CMMotionManager alloc] init]; [_motionManager startAccelerometerUpdates]; + + _deviceOrientationProvider = [[FLTDefaultDeviceOrientationProvider alloc] init]; if (_mediaSettings.framesPerSecond) { // The frame rate can be changed only on a locked for configuration device. @@ -311,7 +316,7 @@ - (instancetype)initWithMediaSettings:(FCPPlatformMediaSettings *)mediaSettings - (AVCaptureConnection *)createConnection:(NSError **)error { // Setup video capture input. - _captureVideoInput = [AVCaptureDeviceInput deviceInputWithDevice:_captureDevice error:error]; + _captureVideoInput = [_captureDevice createInput:error]; // Test the return value of the `deviceInputWithDevice` method to see whether an error occurred. // Don’t just test to see whether the error pointer was set to point to an error. @@ -346,8 +351,8 @@ - (void)reportInitializationState { height:self.previewSize.height] exposureMode:self.exposureMode focusMode:self.focusMode - exposurePointSupported:self.captureDevice.exposurePointOfInterestSupported - focusPointSupported:self.captureDevice.focusPointOfInterestSupported]; + exposurePointSupported:self.captureDevice.isExposurePointOfInterestSupported + focusPointSupported:self.captureDevice.isFocusPointOfInterestSupported]; __weak typeof(self) weakSelf = self; FLTEnsureToRunOnMainQueue(^{ @@ -1041,7 +1046,7 @@ - (void)applyFocusMode { [self applyFocusMode:_focusMode onDevice:_captureDevice]; } -- (void)applyFocusMode:(FCPPlatformFocusMode)focusMode onDevice:(AVCaptureDevice *)captureDevice { +- (void)applyFocusMode:(FCPPlatformFocusMode)focusMode onDevice:(id)captureDevice { [captureDevice lockForConfiguration:nil]; switch (focusMode) { case FCPPlatformFocusModeLocked: @@ -1178,7 +1183,7 @@ - (void)setFocusPoint:(FCPPlatformPoint *)point details:nil]); return; } - UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + UIDeviceOrientation orientation = [_deviceOrientationProvider orientation]; [_captureDevice lockForConfiguration:nil]; // A nil point resets to the center. [_captureDevice diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m index b975daa4b5c2..c712245a6ced 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m @@ -3,14 +3,15 @@ // found in the LICENSE file. #import "./include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h" +#import "./include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h" @implementation FLTCamMediaSettingsAVWrapper -- (BOOL)lockDevice:(AVCaptureDevice *)captureDevice error:(NSError *_Nullable *_Nullable)outError { +- (BOOL)lockDevice:(id)captureDevice error:(NSError *_Nullable *_Nullable)outError { return [captureDevice lockForConfiguration:outError]; } -- (void)unlockDevice:(AVCaptureDevice *)captureDevice { +- (void)unlockDevice:(id)captureDevice { return [captureDevice unlockForConfiguration]; } @@ -22,11 +23,11 @@ - (void)commitConfigurationForSession:(AVCaptureSession *)videoCaptureSession { [videoCaptureSession commitConfiguration]; } -- (void)setMinFrameDuration:(CMTime)duration onDevice:(AVCaptureDevice *)captureDevice { +- (void)setMinFrameDuration:(CMTime)duration onDevice:(id)captureDevice { captureDevice.activeVideoMinFrameDuration = duration; } -- (void)setMaxFrameDuration:(CMTime)duration onDevice:(AVCaptureDevice *)captureDevice { +- (void)setMaxFrameDuration:(CMTime)duration onDevice:(id)captureDevice { captureDevice.activeVideoMaxFrameDuration = duration; } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m new file mode 100644 index 000000000000..f89e44920f48 --- /dev/null +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m @@ -0,0 +1,170 @@ +// 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 "../include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h" + +@interface FLTDefaultCaptureDeviceController () +@property(nonatomic, strong) AVCaptureDevice *device; +@end + +@implementation FLTDefaultCaptureDeviceController + +- (instancetype)initWithDevice:(AVCaptureDevice *)device { + self = [super init]; + if (self) { + _device = device; + } + return self; +} + +// Position/Orientation +- (AVCaptureDevicePosition)position { + return self.device.position; +} + +// Format/Configuration +- (AVCaptureDeviceFormat *)activeFormat { + return self.device.activeFormat; +} + +- (NSArray *)formats { + return self.device.formats; +} + +- (void)setActiveFormat:(AVCaptureDeviceFormat *)format { + self.device.activeFormat = format; +} + +// Flash/Torch +- (BOOL)hasFlash { + return self.device.hasFlash; +} + +- (BOOL)hasTorch { + return self.device.hasTorch; +} + +- (BOOL)isTorchAvailable { + return self.device.isTorchAvailable; +} + +- (AVCaptureTorchMode)torchMode { + return self.device.torchMode; +} + +- (void)setTorchMode:(AVCaptureTorchMode)torchMode { + self.device.torchMode = torchMode; +} + +- (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode { + return [self.device isFlashModeSupported:mode]; +} + +// Focus +- (BOOL)isFocusPointOfInterestSupported { + return self.device.isFocusPointOfInterestSupported; +} + +- (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode { + return [self.device isFocusModeSupported:mode]; +} + +- (void)setFocusMode:(AVCaptureFocusMode)focusMode { + self.device.focusMode = focusMode; +} + +- (void)setFocusPointOfInterest:(CGPoint)point { + self.device.focusPointOfInterest = point; +} + +// Exposure +- (BOOL)isExposurePointOfInterestSupported { + return self.device.isExposurePointOfInterestSupported; +} + +- (void)setExposureMode:(AVCaptureExposureMode)exposureMode { + self.device.exposureMode = exposureMode; +} + +- (void)setExposurePointOfInterest:(CGPoint)point { + self.device.exposurePointOfInterest = point; +} + +- (float)minExposureTargetBias { + return self.device.minExposureTargetBias; +} + +- (float)maxExposureTargetBias { + return self.device.maxExposureTargetBias; +} + +- (void)setExposureTargetBias:(float)bias completionHandler:(void (^)(CMTime))handler { + [self.device setExposureTargetBias:bias completionHandler:handler]; +} + +- (BOOL)isExposureModeSupported:(AVCaptureExposureMode)mode { + return [self.device isExposureModeSupported:mode]; +} + +// Zoom +- (float)maxAvailableVideoZoomFactor { + return self.device.maxAvailableVideoZoomFactor; +} + +- (float)minAvailableVideoZoomFactor { + return self.device.minAvailableVideoZoomFactor; +} + +- (float)videoZoomFactor { + return self.device.videoZoomFactor; +} + +- (void)setVideoZoomFactor:(float)factor { + self.device.videoZoomFactor = factor; +} + +// Camera Properties +- (float)lensAperture { + return self.device.lensAperture; +} + +- (CMTime)exposureDuration { + return self.device.exposureDuration; +} + +- (float)ISO { + return self.device.ISO; +} + +// Configuration Lock +- (BOOL)lockForConfiguration:(NSError **)error { + return [self.device lockForConfiguration:error]; +} + +- (void)unlockForConfiguration { + [self.device unlockForConfiguration]; +} + +- (CMTime)activeVideoMinFrameDuration { + return self.device.activeVideoMinFrameDuration; +} + +- (void)setActiveVideoMinFrameDuration:(CMTime)duration { + self.device.activeVideoMinFrameDuration = duration; +} + +- (CMTime)activeVideoMaxFrameDuration { + return self.device.activeVideoMaxFrameDuration; +} + +- (void)setActiveVideoMaxFrameDuration:(CMTime)duration { + self.device.activeVideoMaxFrameDuration = duration; +} + +- (AVCaptureInput *)createInput:(NSError * _Nullable * _Nullable)error { + return [AVCaptureDeviceInput deviceInputWithDevice:_device error:error]; +} + + +@end diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m new file mode 100644 index 000000000000..7b10f09109d4 --- /dev/null +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m @@ -0,0 +1,13 @@ +// 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 "../include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h" + +@implementation FLTDefaultDeviceOrientationProvider + +- (UIDeviceOrientation)orientation { + return [[UIDevice currentDevice] orientation]; +} + +@end diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap index 57d858f894fa..af0c9bee47fe 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap @@ -13,6 +13,8 @@ framework module camera_avfoundation { header "FLTThreadSafeEventChannel.h" header "FLTPermissionServicing.h" header "FLTCameraPermissionManager.h" + header "FLTCaptureDeviceControlling.h" + header "FLTDeviceOrientationProviding.h" header "QueueUtils.h" } } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h index c89ee9f98e5c..5af5163d2ef2 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h @@ -8,6 +8,7 @@ #import "CameraProperties.h" #import "FLTCamMediaSettingsAVWrapper.h" +#import "FLTCaptureDeviceControlling.h" #import "messages.g.h" NS_ASSUME_NONNULL_BEGIN @@ -15,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN /// A class that manages camera's state and performs camera operations. @interface FLTCam : NSObject -@property(readonly, nonatomic) AVCaptureDevice *captureDevice; +@property(readonly, nonatomic) id captureDevice; @property(readonly, nonatomic) CGSize previewSize; @property(assign, nonatomic) BOOL isPreviewPaused; @property(nonatomic, copy) void (^onFrameAvailable)(void); @@ -92,7 +93,7 @@ NS_ASSUME_NONNULL_BEGIN /// /// @param focusMode The focus mode that should be applied to the @captureDevice instance. /// @param captureDevice The AVCaptureDevice to which the @focusMode will be applied. -- (void)applyFocusMode:(FCPPlatformFocusMode)focusMode onDevice:(AVCaptureDevice *)captureDevice; +- (void)applyFocusMode:(FCPPlatformFocusMode)focusMode onDevice:(id)captureDevice; - (void)pausePreview; - (void)resumePreview; - (void)setDescriptionWhileRecording:(NSString *)cameraName diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h index 144a84eac13f..4e8d9d15cd8f 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h @@ -5,6 +5,8 @@ @import AVFoundation; @import Foundation; +#import "FLTCaptureDeviceControlling.h" + NS_ASSUME_NONNULL_BEGIN /** @@ -25,14 +27,14 @@ NS_ASSUME_NONNULL_BEGIN * @param outError The optional error. * @result A BOOL indicating whether the device was successfully locked for configuration. */ -- (BOOL)lockDevice:(AVCaptureDevice *)captureDevice error:(NSError *_Nullable *_Nullable)outError; +- (BOOL)lockDevice:(id)captureDevice error:(NSError *_Nullable *_Nullable)outError; /** * @method unlockDevice: * @abstract Release exclusive control over device hardware properties. * @param captureDevice The capture device. */ -- (void)unlockDevice:(AVCaptureDevice *)captureDevice; +- (void)unlockDevice:(id)captureDevice; /** * @method beginConfigurationForSession: @@ -57,7 +59,7 @@ NS_ASSUME_NONNULL_BEGIN * @param duration The frame duration. * @param captureDevice The capture device */ -- (void)setMinFrameDuration:(CMTime)duration onDevice:(AVCaptureDevice *)captureDevice; +- (void)setMinFrameDuration:(CMTime)duration onDevice:(id)captureDevice; /** * @method setMaxFrameDuration:onDevice: @@ -66,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN * @param duration The frame duration. * @param captureDevice The capture device */ -- (void)setMaxFrameDuration:(CMTime)duration onDevice:(AVCaptureDevice *)captureDevice; +- (void)setMaxFrameDuration:(CMTime)duration onDevice:(id)captureDevice; /** * @method assetWriterAudioInputWithOutputSettings: diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h index d05838f49a70..65bf90a70b69 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h @@ -4,6 +4,7 @@ #import "FLTCam.h" #import "FLTSavePhotoDelegate.h" +#import "FLTCaptureDeviceControlling.h" /// Determines the video dimensions (width and height) for a given capture device format. /// Used in tests to mock CMVideoFormatDescriptionGetDimensions. @@ -11,7 +12,7 @@ typedef CMVideoDimensions (^VideoDimensionsForFormat)(AVCaptureDeviceFormat *); /// Factory block returning an AVCaptureDevice. /// Used in tests to inject a device into FLTCam. -typedef AVCaptureDevice * (^CaptureDeviceFactory)(void); +typedef id (^CaptureDeviceFactory)(void); @interface FLTImageStreamHandler : NSObject diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h new file mode 100644 index 000000000000..5603055865aa --- /dev/null +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h @@ -0,0 +1,72 @@ +// 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 AVFoundation; +@import Foundation; + +NS_ASSUME_NONNULL_BEGIN + +@protocol FLTCaptureDeviceControlling + +// Position/Orientation +- (AVCaptureDevicePosition)position; + +// Format/Configuration +- (AVCaptureDeviceFormat *)activeFormat; +- (NSArray *)formats; +- (void)setActiveFormat:(AVCaptureDeviceFormat *)format; + +// Flash/Torch +- (BOOL)hasFlash; +- (BOOL)hasTorch; +- (BOOL)isTorchAvailable; +- (AVCaptureTorchMode)torchMode; +- (void)setTorchMode:(AVCaptureTorchMode)torchMode; +- (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode; + +// Focus +- (BOOL)isFocusPointOfInterestSupported; +- (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode; +- (void)setFocusMode:(AVCaptureFocusMode)focusMode; +- (void)setFocusPointOfInterest:(CGPoint)point; + +// Exposure +- (BOOL)isExposurePointOfInterestSupported; +- (void)setExposureMode:(AVCaptureExposureMode)exposureMode; +- (void)setExposurePointOfInterest:(CGPoint)point; +- (float)minExposureTargetBias; +- (float)maxExposureTargetBias; +- (void)setExposureTargetBias:(float)bias completionHandler:(void (^ _Nullable)(CMTime))handler; +- (BOOL)isExposureModeSupported:(AVCaptureExposureMode)mode; + +// Zoom +- (float)maxAvailableVideoZoomFactor; +- (float)minAvailableVideoZoomFactor; +- (float)videoZoomFactor; +- (void)setVideoZoomFactor:(float)factor; + +// Camera Properties +- (float)lensAperture; +- (CMTime)exposureDuration; +- (float)ISO; + +// Configuration Lock +- (BOOL)lockForConfiguration:(NSError **)error; +- (void)unlockForConfiguration; + +// Frame Duration +- (CMTime)activeVideoMinFrameDuration; +- (void)setActiveVideoMinFrameDuration:(CMTime)duration; +- (CMTime)activeVideoMaxFrameDuration; +- (void)setActiveVideoMaxFrameDuration:(CMTime)duration; + +- (AVCaptureInput *)createInput:(NSError * _Nullable * _Nullable)error; + +@end + +@interface FLTDefaultCaptureDeviceController : NSObject +- (instancetype)initWithDevice:(AVCaptureDevice *)device; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h new file mode 100644 index 000000000000..e0b39f9b9e21 --- /dev/null +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h @@ -0,0 +1,17 @@ +// 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 AVFoundation; +@import Foundation; + +NS_ASSUME_NONNULL_BEGIN + +@protocol FLTDeviceOrientationProviding +- (UIDeviceOrientation)orientation; +@end + +@interface FLTDefaultDeviceOrientationProvider : NSObject +@end + +NS_ASSUME_NONNULL_END From 34980c5a9a3aabc6fdce6c5835b47e8a093dd4a9 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Fri, 6 Dec 2024 17:14:26 +0100 Subject: [PATCH 02/16] Migrate CameraExposureTests --- .../xcshareddata/swiftpm/Package.resolved | 14 ---- .../ios/RunnerTests/CameraExposureTests.m | 78 ++++++++++++------- .../ios/RunnerTests/CameraFocusTests.m | 28 ++++++- .../ios/RunnerTests/CameraOrientationTests.m | 15 +++- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 2 +- .../RunnerTests/MockCaptureDeviceController.h | 7 +- .../RunnerTests/MockCaptureDeviceController.m | 3 +- .../RunnerTests/Mocks/MockDeviceController.m | 6 -- .../Protocols/FLTCaptureDeviceControlling.m | 2 +- 9 files changed, 94 insertions(+), 61 deletions(-) delete mode 100644 packages/camera/camera_avfoundation/example/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved delete mode 100644 packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockDeviceController.m diff --git a/packages/camera/camera_avfoundation/example/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/packages/camera/camera_avfoundation/example/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index a8d31f4703ec..000000000000 --- a/packages/camera/camera_avfoundation/example/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,14 +0,0 @@ -{ - "originHash" : "20e8ffe6c32a926c4f00e4e9a967104dab3f8007aacc282029f03ed5f5f2e183", - "pins" : [ - { - "identity" : "ocmock", - "kind" : "remoteSourceControl", - "location" : "https://github.com/erikdoe/ocmock", - "state" : { - "revision" : "fe1661a3efed11831a6452f4b1a0c5e6ddc08c3d" - } - } - ], - "version" : 3 -} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m index 7b641a5746c0..bbe3cf055a9a 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m @@ -5,51 +5,73 @@ @import camera_avfoundation; @import XCTest; @import AVFoundation; -#import -@interface FLTCam : NSObject - -- (void)setExposurePointWithResult:(FlutterResult)result x:(double)x y:(double)y; -@end +#import "MockCaptureDeviceController.h" +#import "MockDeviceOrientationProvider.h" @interface CameraExposureTests : XCTestCase @property(readonly, nonatomic) FLTCam *camera; -@property(readonly, nonatomic) id mockDevice; -@property(readonly, nonatomic) id mockUIDevice; +@property(readonly, nonatomic) MockCaptureDeviceController *mockDevice; +@property(readonly, nonatomic) MockDeviceOrientationProvider *mockDeviceOrientationProvider; @end @implementation CameraExposureTests - (void)setUp { _camera = [[FLTCam alloc] init]; - _mockDevice = OCMClassMock([AVCaptureDevice class]); - _mockUIDevice = OCMPartialMock([UIDevice currentDevice]); -} - -- (void)tearDown { - [_mockDevice stopMocking]; - [_mockUIDevice stopMocking]; + _mockDevice = [[MockCaptureDeviceController alloc] init]; + _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; + + [_camera setValue:_mockDevice forKey:@"captureDevice"]; + [_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"]; } -- (void)testSetExpsourePointWithResult_SetsExposurePointOfInterest { +- (void)testSetExposurePointWithResult_SetsExposurePointOfInterest { // UI is currently in landscape left orientation - OCMStub([(UIDevice *)_mockUIDevice orientation]).andReturn(UIDeviceOrientationLandscapeLeft); + _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Exposure point of interest is supported - OCMStub([_mockDevice isExposurePointOfInterestSupported]).andReturn(true); - // Set mock device as the current capture device - [_camera setValue:_mockDevice forKey:@"captureDevice"]; + _mockDevice.isExposurePointOfInterestSupported = YES; + + // Verify the focus point of interest has been set + __block CGPoint setPoint = CGPointZero; + _mockDevice.setExposurePointOfInterestStub = ^(CGPoint point) { + if (CGPointEqualToPoint(CGPointMake(1, 1), point)) { + setPoint = point; + } + }; // Run test - [_camera - setExposurePointWithResult:^void(id _Nullable result) { - } - x:1 - y:1]; + XCTestExpectation *completionExpectation = [self expectationWithDescription:@"Completion called"]; + [_camera setExposurePoint:[FCPPlatformPoint makeWithX:1 y:1] + withCompletion:^(FlutterError * _Nullable error) { + XCTAssertNil(error); + [completionExpectation fulfill]; + }]; - // Verify the focus point of interest has been set - OCMVerify([_mockDevice setExposurePointOfInterest:CGPointMake(1, 1)]); + [self waitForExpectationsWithTimeout:1 handler:nil]; + XCTAssertEqual(setPoint.x, 1.0); + XCTAssertEqual(setPoint.y, 1.0); +} + +- (void)testSetExposurePoint_WhenNotSupported_ReturnsError { + // UI is currently in landscape left orientation + _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; + // Exposure point of interest is not supported + _mockDevice.isExposurePointOfInterestSupported = NO; + + XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"]; + + // Run + [_camera setExposurePoint:[FCPPlatformPoint makeWithX:1 y:1] + withCompletion:^(FlutterError *_Nullable error) { + XCTAssertNotNil(error); + XCTAssertEqualObjects(error.code, @"setExposurePointFailed"); + XCTAssertEqualObjects(error.message, @"Device does not have exposure point capabilities"); + [expectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:1 handler:nil]; } @end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m index edcd7c4795c7..27f5e21bdfab 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m @@ -24,6 +24,9 @@ - (void)setUp { _camera = [[FLTCam alloc] init]; _mockDevice = [[MockCaptureDeviceController alloc] init]; _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; + + [_camera setValue:_mockDevice forKey:@"captureDevice"]; + [_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"]; } - (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus { @@ -127,15 +130,11 @@ - (void)testLockedFocusWithModeNotSupported_ShouldSetNothing { [_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice]; } -// TODO(mchudy): replace setValue with proper DI - (void)testSetFocusPointWithResult_SetsFocusPointOfInterest { // UI is currently in landscape left orientation - [_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"]; _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Focus point of interest is supported _mockDevice.isFocusPointOfInterestSupported = YES; - // Set mock device as the current capture device - [_camera setValue:_mockDevice forKey:@"captureDevice"]; __block BOOL setFocusPointOfInterestCalled = NO; _mockDevice.setFocusPointOfInterestStub = ^(CGPoint point) { @@ -153,4 +152,25 @@ - (void)testSetFocusPointWithResult_SetsFocusPointOfInterest { XCTAssertTrue(setFocusPointOfInterestCalled); } +- (void)testSetFocusPoint_WhenNotSupported_ReturnsError { + // UI is currently in landscape left orientation + _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; + // Exposure point of interest is not supported + _mockDevice.isFocusPointOfInterestSupported = NO; + + XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"]; + + // Run + [_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1] + withCompletion:^(FlutterError *_Nullable error) { + XCTAssertNotNil(error); + XCTAssertEqualObjects(error.code, @"setFocusPointFailed"); + XCTAssertEqualObjects(error.message, @"Device does not have focus point capabilities"); + [expectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + @end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m index e6ce8d48bc5b..6ced4fa4c4e6 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m @@ -11,6 +11,8 @@ #import +#import "MockCaptureDeviceController.h" + @interface StubGlobalEventApi : FCPCameraGlobalEventApi @property(nonatomic) BOOL called; @property(nonatomic) FCPPlatformDeviceOrientation lastOrientation; @@ -35,10 +37,21 @@ - (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(nonnull NSString #pragma mark - @interface CameraOrientationTests : XCTestCase +@property(readonly, nonatomic) FLTCam *camera; +@property(readonly, nonatomic) MockCaptureDeviceController *mockDevice; +@property(readonly, nonatomic) StubGlobalEventApi *eventAPI; @end @implementation CameraOrientationTests +- (void)setUp { + [super setUp]; + _mockDevice = [[MockCaptureDeviceController alloc] init]; + _camera = [[FLTCam alloc] init]; + + [_camera setValue:_mockDevice forKey:@"captureDevice"]; +} + // Ensure that the given queue and then the main queue have both cycled, to wait for any pending // async events that may have been bounced between them. - (void)waitForRoundTripWithQueue:(dispatch_queue_t)queue { @@ -97,13 +110,13 @@ - (void)testOrientationNotificationsNotCalledForFaceDown { - (void)testOrientationUpdateMustBeOnCaptureSessionQueue { XCTestExpectation *queueExpectation = [self expectationWithDescription:@"Orientation update must happen on the capture session queue"]; - CameraPlugin *camera = [[CameraPlugin alloc] initWithRegistry:nil messenger:nil]; const char *captureSessionQueueSpecific = "capture_session_queue"; dispatch_queue_set_specific(camera.captureSessionQueue, captureSessionQueueSpecific, (void *)captureSessionQueueSpecific, NULL); FLTCam *mockCam = OCMClassMock([FLTCam class]); camera.camera = mockCam; + OCMStub([mockCam setDeviceOrientation:UIDeviceOrientationLandscapeLeft]) .andDo(^(NSInvocation *invocation) { if (dispatch_get_specific(captureSessionQueueSpecific)) { diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 31711f065efd..bc7e224e549e 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -171,7 +171,7 @@ - (void)testCaptureToFile_mustReportFileExtensionWithJpgWhenHEVCNotAvailableAndF }); [self waitForExpectationsWithTimeout:1 handler:nil]; } -// + - (void)testCaptureToFile_handlesTorchMode { XCTestExpectation *pathExpectation = [self expectationWithDescription: diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h index 8723b1910244..901bcc60c7b1 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h @@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, assign) BOOL flashModeSupported; // Focus -@property(nonatomic, assign) BOOL focusPointOfInterestSupported; +@property(nonatomic, assign) BOOL isFocusPointOfInterestSupported; @property(nonatomic, copy) BOOL (^isFocusModeSupportedStub)(AVCaptureFocusMode mode); @property(nonatomic, assign) AVCaptureFocusMode focusMode; @property(nonatomic, copy) void (^setFocusModeStub)(AVCaptureFocusMode mode); @@ -36,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy) void (^setFocusPointOfInterestStub)(CGPoint point); // Exposure -@property(nonatomic, assign) BOOL exposurePointOfInterestSupported; +@property(nonatomic, assign) BOOL isExposurePointOfInterestSupported; @property(nonatomic, assign) AVCaptureExposureMode exposureMode; @property(nonatomic, assign) BOOL exposureModeSupported; @property(nonatomic, copy) void (^setExposureModeStub)(AVCaptureExposureMode mode); @@ -72,9 +72,6 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong) AVCaptureInput *inputToReturn; @property(nonatomic, copy) void (^createInputStub)(NSError **error); -@property(nonatomic, assign) BOOL isExposurePointOfInterestSupported; -@property(nonatomic, assign) BOOL isFocusPointOfInterestSupported; - @end NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m index c1659d36f07d..548cea98bb9c 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m @@ -68,6 +68,8 @@ - (void)setExposurePointOfInterest:(CGPoint)point { - (void)setExposureTargetBias:(float)bias completionHandler:(void (^)(CMTime))handler { if (self.setExposureTargetBiasStub) { self.setExposureTargetBiasStub(bias, handler); + } else if (handler) { + handler(kCMTimeZero); } } @@ -123,5 +125,4 @@ - (AVCaptureInput *)createInput:(NSError *_Nullable *_Nullable)error { return self.inputToReturn; } - @end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockDeviceController.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockDeviceController.m deleted file mode 100644 index 27cc985d7d2b..000000000000 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockDeviceController.m +++ /dev/null @@ -1,6 +0,0 @@ -// 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. - - -@interface FLTMockCaptureDeviceController : NSObject diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m index f89e44920f48..1483620039b4 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m @@ -63,7 +63,7 @@ - (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode { // Focus - (BOOL)isFocusPointOfInterestSupported { - return self.device.isFocusPointOfInterestSupported; + return self.device.isFocusPointOfInterestSupported; } - (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode { From a0a0f72b0eb683272d8627156c77b4a625cabeeb Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Fri, 27 Dec 2024 14:26:42 +0100 Subject: [PATCH 03/16] Format code --- .../ios/RunnerTests/CameraExposureTests.m | 31 ++--- .../ios/RunnerTests/CameraFocusTests.m | 38 +++--- .../ios/RunnerTests/CameraOrientationTests.m | 2 +- .../example/ios/RunnerTests/CameraTestUtils.m | 22 ++-- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 9 +- .../RunnerTests/MockCaptureDeviceController.h | 3 +- .../RunnerTests/MockCaptureDeviceController.m | 120 +++++++++--------- .../Sources/camera_avfoundation/FLTCam.m | 15 ++- .../FLTCamMediaSettingsAVWrapper.m | 9 +- .../Protocols/FLTCaptureDeviceControlling.m | 77 ++++++----- .../Protocols/FLTDeviceOrientationProviding.m | 2 +- .../include/camera_avfoundation/FLTCam.h | 3 +- .../FLTCamMediaSettingsAVWrapper.h | 9 +- .../include/camera_avfoundation/FLTCam_Test.h | 2 +- .../Protocols/FLTCaptureDeviceControlling.h | 4 +- .../include/camera_avfoundation/QueueUtils.h | 2 +- 16 files changed, 179 insertions(+), 169 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m index bbe3cf055a9a..28a5f7e1fcce 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m @@ -21,7 +21,7 @@ - (void)setUp { _camera = [[FLTCam alloc] init]; _mockDevice = [[MockCaptureDeviceController alloc] init]; _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; - + [_camera setValue:_mockDevice forKey:@"captureDevice"]; [_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"]; } @@ -31,7 +31,7 @@ - (void)testSetExposurePointWithResult_SetsExposurePointOfInterest { _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Exposure point of interest is supported _mockDevice.isExposurePointOfInterestSupported = YES; - + // Verify the focus point of interest has been set __block CGPoint setPoint = CGPointZero; _mockDevice.setExposurePointOfInterestStub = ^(CGPoint point) { @@ -43,9 +43,9 @@ - (void)testSetExposurePointWithResult_SetsExposurePointOfInterest { // Run test XCTestExpectation *completionExpectation = [self expectationWithDescription:@"Completion called"]; [_camera setExposurePoint:[FCPPlatformPoint makeWithX:1 y:1] - withCompletion:^(FlutterError * _Nullable error) { - XCTAssertNil(error); - [completionExpectation fulfill]; + withCompletion:^(FlutterError *_Nullable error) { + XCTAssertNil(error); + [completionExpectation fulfill]; }]; [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -58,18 +58,19 @@ - (void)testSetExposurePoint_WhenNotSupported_ReturnsError { _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Exposure point of interest is not supported _mockDevice.isExposurePointOfInterestSupported = NO; - + XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"]; - + // Run - [_camera setExposurePoint:[FCPPlatformPoint makeWithX:1 y:1] - withCompletion:^(FlutterError *_Nullable error) { - XCTAssertNotNil(error); - XCTAssertEqualObjects(error.code, @"setExposurePointFailed"); - XCTAssertEqualObjects(error.message, @"Device does not have exposure point capabilities"); - [expectation fulfill]; - }]; - + [_camera + setExposurePoint:[FCPPlatformPoint makeWithX:1 y:1] + withCompletion:^(FlutterError *_Nullable error) { + XCTAssertNotNil(error); + XCTAssertEqualObjects(error.code, @"setExposurePointFailed"); + XCTAssertEqualObjects(error.message, @"Device does not have exposure point capabilities"); + [expectation fulfill]; + }]; + // Verify [self waitForExpectationsWithTimeout:1 handler:nil]; } diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m index 27f5e21bdfab..f7d96c3aa75c 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m @@ -24,7 +24,7 @@ - (void)setUp { _camera = [[FLTCam alloc] init]; _mockDevice = [[MockCaptureDeviceController alloc] init]; _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; - + [_camera setValue:_mockDevice forKey:@"captureDevice"]; [_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"]; } @@ -34,7 +34,7 @@ - (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus { _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus; }; - + __block BOOL setFocusModeContinuousAutoFocusCalled = NO; _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { @@ -59,9 +59,9 @@ - (void)testAutoFocusWithContinuousModeNotSupported_ShouldSetAutoFocus { _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { return mode == AVCaptureFocusModeAutoFocus; }; - + __block BOOL setFocusModeAutoFocusCalled = NO; - + // Don't expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { if (mode == AVCaptureFocusModeContinuousAutoFocus) { @@ -70,10 +70,10 @@ - (void)testAutoFocusWithContinuousModeNotSupported_ShouldSetAutoFocus { setFocusModeAutoFocusCalled = YES; } }; - + // Run test [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; - + // Expect setFocusMode:AVCaptureFocusModeAutoFocus XCTAssertTrue(setFocusModeAutoFocusCalled); } @@ -86,7 +86,7 @@ - (void)testAutoFocusWithNoModeSupported_ShouldSetNothing { // Don't expect any setFocus _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { - XCTFail(@"Unexpected call to setFocusMode"); + XCTFail(@"Unexpected call to setFocusMode"); }; // Run test @@ -98,7 +98,7 @@ - (void)testLockedFocusWithModeSupported_ShouldSetModeAutoFocus { _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus; }; - + __block BOOL setFocusModeAutoFocusCalled = NO; // Expect only setFocusMode:AVCaptureFocusModeAutoFocus @@ -109,7 +109,7 @@ - (void)testLockedFocusWithModeSupported_ShouldSetModeAutoFocus { setFocusModeAutoFocusCalled = YES; } }; - + // Run test [_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice]; @@ -123,7 +123,7 @@ - (void)testLockedFocusWithModeNotSupported_ShouldSetNothing { // Don't expect any setFocus _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { - XCTFail(@"Unexpected call to setFocusMode"); + XCTFail(@"Unexpected call to setFocusMode"); }; // Run test @@ -157,18 +157,18 @@ - (void)testSetFocusPoint_WhenNotSupported_ReturnsError { _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Exposure point of interest is not supported _mockDevice.isFocusPointOfInterestSupported = NO; - + XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"]; - + // Run [_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1] - withCompletion:^(FlutterError *_Nullable error) { - XCTAssertNotNil(error); - XCTAssertEqualObjects(error.code, @"setFocusPointFailed"); - XCTAssertEqualObjects(error.message, @"Device does not have focus point capabilities"); - [expectation fulfill]; - }]; - + withCompletion:^(FlutterError *_Nullable error) { + XCTAssertNotNil(error); + XCTAssertEqualObjects(error.code, @"setFocusPointFailed"); + XCTAssertEqualObjects(error.message, @"Device does not have focus point capabilities"); + [expectation fulfill]; + }]; + // Verify [self waitForExpectationsWithTimeout:1 handler:nil]; } diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m index 6ced4fa4c4e6..b1547c53212c 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m @@ -116,7 +116,7 @@ - (void)testOrientationUpdateMustBeOnCaptureSessionQueue { (void *)captureSessionQueueSpecific, NULL); FLTCam *mockCam = OCMClassMock([FLTCam class]); camera.camera = mockCam; - + OCMStub([mockCam setDeviceOrientation:UIDeviceOrientationLandscapeLeft]) .andDo(^(NSInvocation *invocation) { if (dispatch_get_specific(captureSessionQueueSpecific)) { diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m index 501498d6382b..f82bbf1aedc9 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m @@ -155,16 +155,18 @@ OCMStub([audioSessionMock addInputWithNoConnections:[OCMArg any]]); OCMStub([audioSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES); - return [[FLTCam alloc] initWithMediaSettings:FCPGetDefaultMediaSettings(resolutionPreset) - mediaSettingsAVWrapper:[[FLTCamMediaSettingsAVWrapper alloc] init] - orientation:UIDeviceOrientationPortrait - videoCaptureSession:captureSession - audioCaptureSession:audioSessionMock - captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL) - captureDeviceFactory:^id(void) { - return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDevice]; } - videoDimensionsForFormat:videoDimensionsForFormat - error:nil]; + return [[FLTCam alloc] + initWithMediaSettings:FCPGetDefaultMediaSettings(resolutionPreset) + mediaSettingsAVWrapper:[[FLTCamMediaSettingsAVWrapper alloc] init] + orientation:UIDeviceOrientationPortrait + videoCaptureSession:captureSession + audioCaptureSession:audioSessionMock + captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL) + captureDeviceFactory:^id(void) { + return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDevice]; + } + videoDimensionsForFormat:videoDimensionsForFormat + error:nil]; } CMSampleBufferRef FLTCreateTestSampleBuffer(void) { diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index bc7e224e549e..75a4f3abd7d0 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -187,11 +187,10 @@ - (void)testCaptureToFile_handlesTorchMode { dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); - FLTCam *cam = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(captureSessionQueue, nil, nil, - ^id(void) { - return - [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDeviceMock]; - }); + FLTCam *cam = FLTCreateCamWithCaptureSessionQueueAndMediaSettings( + captureSessionQueue, nil, nil, ^id(void) { + return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDeviceMock]; + }); AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h index 901bcc60c7b1..af28d652734a 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h @@ -44,7 +44,8 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy) void (^setExposurePointOfInterestStub)(CGPoint point); @property(nonatomic, assign) float minExposureTargetBias; @property(nonatomic, assign) float maxExposureTargetBias; -@property(nonatomic, copy) void (^setExposureTargetBiasStub)(float bias, void (^_Nullable handler)(CMTime)); +@property(nonatomic, copy) void (^setExposureTargetBiasStub) + (float bias, void (^_Nullable handler)(CMTime)); // Zoom @property(nonatomic, assign) float maxAvailableVideoZoomFactor; diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m index 548cea98bb9c..cc89bb85abf8 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m @@ -13,21 +13,21 @@ @implementation MockCaptureDeviceController - (void)setActiveFormat:(AVCaptureDeviceFormat *)format { - _activeFormat = format; - if (self.setActiveFormatStub) { - self.setActiveFormatStub(format); - } + _activeFormat = format; + if (self.setActiveFormatStub) { + self.setActiveFormatStub(format); + } } - (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode { - return self.flashModeSupported; + return self.flashModeSupported; } - (void)setTorchMode:(AVCaptureTorchMode)mode { - _torchMode = mode; - if (self.setTorchModeStub) { - self.setTorchModeStub(mode); - } + _torchMode = mode; + if (self.setTorchModeStub) { + self.setTorchModeStub(mode); + } } - (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode { @@ -38,91 +38,91 @@ - (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode { } - (void)setFocusMode:(AVCaptureFocusMode)mode { - _focusMode = mode; - if (self.setFocusModeStub) { - self.setFocusModeStub(mode); - } + _focusMode = mode; + if (self.setFocusModeStub) { + self.setFocusModeStub(mode); + } } - (void)setFocusPointOfInterest:(CGPoint)point { - _focusPointOfInterest = point; - if (self.setFocusPointOfInterestStub) { - self.setFocusPointOfInterestStub(point); - } + _focusPointOfInterest = point; + if (self.setFocusPointOfInterestStub) { + self.setFocusPointOfInterestStub(point); + } } - (void)setExposureMode:(AVCaptureExposureMode)mode { - _exposureMode = mode; - if (self.setExposureModeStub) { - self.setExposureModeStub(mode); - } + _exposureMode = mode; + if (self.setExposureModeStub) { + self.setExposureModeStub(mode); + } } - (void)setExposurePointOfInterest:(CGPoint)point { - _exposurePointOfInterest = point; - if (self.setExposurePointOfInterestStub) { - self.setExposurePointOfInterestStub(point); - } + _exposurePointOfInterest = point; + if (self.setExposurePointOfInterestStub) { + self.setExposurePointOfInterestStub(point); + } } - (void)setExposureTargetBias:(float)bias completionHandler:(void (^)(CMTime))handler { - if (self.setExposureTargetBiasStub) { - self.setExposureTargetBiasStub(bias, handler); - } else if (handler) { - handler(kCMTimeZero); - } + if (self.setExposureTargetBiasStub) { + self.setExposureTargetBiasStub(bias, handler); + } else if (handler) { + handler(kCMTimeZero); + } } - (void)setVideoZoomFactor:(float)factor { - _videoZoomFactor = factor; - if (self.setVideoZoomFactorStub) { - self.setVideoZoomFactorStub(factor); - } + _videoZoomFactor = factor; + if (self.setVideoZoomFactorStub) { + self.setVideoZoomFactorStub(factor); + } } - (BOOL)lockForConfiguration:(NSError **)error { - if (self.lockForConfigurationStub) { - self.lockForConfigurationStub(error); - return !self.shouldFailConfiguration; - } - if (self.shouldFailConfiguration) { - if (error) { - *error = [NSError errorWithDomain:@"test" code:0 userInfo:nil]; - } - return NO; + if (self.lockForConfigurationStub) { + self.lockForConfigurationStub(error); + return !self.shouldFailConfiguration; + } + if (self.shouldFailConfiguration) { + if (error) { + *error = [NSError errorWithDomain:@"test" code:0 userInfo:nil]; } - return YES; + return NO; + } + return YES; } - (void)unlockForConfiguration { - if (self.unlockForConfigurationStub) { - self.unlockForConfigurationStub(); - } + if (self.unlockForConfigurationStub) { + self.unlockForConfigurationStub(); + } } - (void)setActiveVideoMinFrameDuration:(CMTime)duration { - _activeVideoMinFrameDuration = duration; - if (self.setActiveVideoMinFrameDurationStub) { - self.setActiveVideoMinFrameDurationStub(duration); - } + _activeVideoMinFrameDuration = duration; + if (self.setActiveVideoMinFrameDurationStub) { + self.setActiveVideoMinFrameDurationStub(duration); + } } - (void)setActiveVideoMaxFrameDuration:(CMTime)duration { - _activeVideoMaxFrameDuration = duration; - if (self.setActiveVideoMaxFrameDurationStub) { - self.setActiveVideoMaxFrameDurationStub(duration); - } + _activeVideoMaxFrameDuration = duration; + if (self.setActiveVideoMaxFrameDurationStub) { + self.setActiveVideoMaxFrameDurationStub(duration); + } } - (BOOL)isExposureModeSupported:(AVCaptureExposureMode)mode { - return self.exposureModeSupported; + return self.exposureModeSupported; } - (AVCaptureInput *)createInput:(NSError *_Nullable *_Nullable)error { - if (self.createInputStub) { - self.createInputStub(error); - } - return self.inputToReturn; + if (self.createInputStub) { + self.createInputStub(error); + } + return self.inputToReturn; } @end diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m index beb2c2ad6329..34c5fcac41e8 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m @@ -11,10 +11,10 @@ #import "./include/camera_avfoundation/FLTSavePhotoDelegate.h" #import "./include/camera_avfoundation/FLTThreadSafeEventChannel.h" -#import "./include/camera_avfoundation/QueueUtils.h" -#import "./include/camera_avfoundation/messages.g.h" #import "./include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h" #import "./include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h" +#import "./include/camera_avfoundation/QueueUtils.h" +#import "./include/camera_avfoundation/messages.g.h" static FlutterError *FlutterErrorFromNSError(NSError *error) { return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %d", (int)error.code] @@ -146,7 +146,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName videoCaptureSession:videoCaptureSession audioCaptureSession:videoCaptureSession captureSessionQueue:captureSessionQueue - captureDeviceFactory:^id (void) { + captureDeviceFactory:^id(void) { AVCaptureDevice *device = [AVCaptureDevice deviceWithUniqueID:cameraName]; return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:device]; } @@ -267,7 +267,7 @@ - (instancetype)initWithMediaSettings:(FCPPlatformMediaSettings *)mediaSettings _motionManager = [[CMMotionManager alloc] init]; [_motionManager startAccelerometerUpdates]; - + _deviceOrientationProvider = [[FLTDefaultDeviceOrientationProvider alloc] init]; if (_mediaSettings.framesPerSecond) { @@ -351,8 +351,8 @@ - (void)reportInitializationState { height:self.previewSize.height] exposureMode:self.exposureMode focusMode:self.focusMode - exposurePointSupported:self.captureDevice.isExposurePointOfInterestSupported - focusPointSupported:self.captureDevice.isFocusPointOfInterestSupported]; + exposurePointSupported:self.captureDevice.isExposurePointOfInterestSupported + focusPointSupported:self.captureDevice.isFocusPointOfInterestSupported]; __weak typeof(self) weakSelf = self; FLTEnsureToRunOnMainQueue(^{ @@ -1046,7 +1046,8 @@ - (void)applyFocusMode { [self applyFocusMode:_focusMode onDevice:_captureDevice]; } -- (void)applyFocusMode:(FCPPlatformFocusMode)focusMode onDevice:(id)captureDevice { +- (void)applyFocusMode:(FCPPlatformFocusMode)focusMode + onDevice:(id)captureDevice { [captureDevice lockForConfiguration:nil]; switch (focusMode) { case FCPPlatformFocusModeLocked: diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m index c712245a6ced..0ecf89a724ce 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m @@ -7,7 +7,8 @@ @implementation FLTCamMediaSettingsAVWrapper -- (BOOL)lockDevice:(id)captureDevice error:(NSError *_Nullable *_Nullable)outError { +- (BOOL)lockDevice:(id)captureDevice + error:(NSError *_Nullable *_Nullable)outError { return [captureDevice lockForConfiguration:outError]; } @@ -23,11 +24,13 @@ - (void)commitConfigurationForSession:(AVCaptureSession *)videoCaptureSession { [videoCaptureSession commitConfiguration]; } -- (void)setMinFrameDuration:(CMTime)duration onDevice:(id)captureDevice { +- (void)setMinFrameDuration:(CMTime)duration + onDevice:(id)captureDevice { captureDevice.activeVideoMinFrameDuration = duration; } -- (void)setMaxFrameDuration:(CMTime)duration onDevice:(id)captureDevice { +- (void)setMaxFrameDuration:(CMTime)duration + onDevice:(id)captureDevice { captureDevice.activeVideoMaxFrameDuration = duration; } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m index 1483620039b4..eaa4dfd250aa 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m @@ -11,54 +11,54 @@ @interface FLTDefaultCaptureDeviceController () @implementation FLTDefaultCaptureDeviceController - (instancetype)initWithDevice:(AVCaptureDevice *)device { - self = [super init]; - if (self) { - _device = device; - } - return self; + self = [super init]; + if (self) { + _device = device; + } + return self; } // Position/Orientation - (AVCaptureDevicePosition)position { - return self.device.position; + return self.device.position; } // Format/Configuration - (AVCaptureDeviceFormat *)activeFormat { - return self.device.activeFormat; + return self.device.activeFormat; } - (NSArray *)formats { - return self.device.formats; + return self.device.formats; } - (void)setActiveFormat:(AVCaptureDeviceFormat *)format { - self.device.activeFormat = format; + self.device.activeFormat = format; } // Flash/Torch - (BOOL)hasFlash { - return self.device.hasFlash; + return self.device.hasFlash; } - (BOOL)hasTorch { - return self.device.hasTorch; + return self.device.hasTorch; } - (BOOL)isTorchAvailable { - return self.device.isTorchAvailable; + return self.device.isTorchAvailable; } - (AVCaptureTorchMode)torchMode { - return self.device.torchMode; + return self.device.torchMode; } - (void)setTorchMode:(AVCaptureTorchMode)torchMode { - self.device.torchMode = torchMode; + self.device.torchMode = torchMode; } - (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode { - return [self.device isFlashModeSupported:mode]; + return [self.device isFlashModeSupported:mode]; } // Focus @@ -67,40 +67,40 @@ - (BOOL)isFocusPointOfInterestSupported { } - (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode { - return [self.device isFocusModeSupported:mode]; + return [self.device isFocusModeSupported:mode]; } - (void)setFocusMode:(AVCaptureFocusMode)focusMode { - self.device.focusMode = focusMode; + self.device.focusMode = focusMode; } - (void)setFocusPointOfInterest:(CGPoint)point { - self.device.focusPointOfInterest = point; + self.device.focusPointOfInterest = point; } // Exposure - (BOOL)isExposurePointOfInterestSupported { - return self.device.isExposurePointOfInterestSupported; + return self.device.isExposurePointOfInterestSupported; } - (void)setExposureMode:(AVCaptureExposureMode)exposureMode { - self.device.exposureMode = exposureMode; + self.device.exposureMode = exposureMode; } - (void)setExposurePointOfInterest:(CGPoint)point { - self.device.exposurePointOfInterest = point; + self.device.exposurePointOfInterest = point; } - (float)minExposureTargetBias { - return self.device.minExposureTargetBias; + return self.device.minExposureTargetBias; } - (float)maxExposureTargetBias { - return self.device.maxExposureTargetBias; + return self.device.maxExposureTargetBias; } - (void)setExposureTargetBias:(float)bias completionHandler:(void (^)(CMTime))handler { - [self.device setExposureTargetBias:bias completionHandler:handler]; + [self.device setExposureTargetBias:bias completionHandler:handler]; } - (BOOL)isExposureModeSupported:(AVCaptureExposureMode)mode { @@ -109,62 +109,61 @@ - (BOOL)isExposureModeSupported:(AVCaptureExposureMode)mode { // Zoom - (float)maxAvailableVideoZoomFactor { - return self.device.maxAvailableVideoZoomFactor; + return self.device.maxAvailableVideoZoomFactor; } - (float)minAvailableVideoZoomFactor { - return self.device.minAvailableVideoZoomFactor; + return self.device.minAvailableVideoZoomFactor; } - (float)videoZoomFactor { - return self.device.videoZoomFactor; + return self.device.videoZoomFactor; } - (void)setVideoZoomFactor:(float)factor { - self.device.videoZoomFactor = factor; + self.device.videoZoomFactor = factor; } // Camera Properties - (float)lensAperture { - return self.device.lensAperture; + return self.device.lensAperture; } - (CMTime)exposureDuration { - return self.device.exposureDuration; + return self.device.exposureDuration; } - (float)ISO { - return self.device.ISO; + return self.device.ISO; } // Configuration Lock - (BOOL)lockForConfiguration:(NSError **)error { - return [self.device lockForConfiguration:error]; + return [self.device lockForConfiguration:error]; } - (void)unlockForConfiguration { - [self.device unlockForConfiguration]; + [self.device unlockForConfiguration]; } - (CMTime)activeVideoMinFrameDuration { - return self.device.activeVideoMinFrameDuration; + return self.device.activeVideoMinFrameDuration; } - (void)setActiveVideoMinFrameDuration:(CMTime)duration { - self.device.activeVideoMinFrameDuration = duration; + self.device.activeVideoMinFrameDuration = duration; } - (CMTime)activeVideoMaxFrameDuration { - return self.device.activeVideoMaxFrameDuration; + return self.device.activeVideoMaxFrameDuration; } - (void)setActiveVideoMaxFrameDuration:(CMTime)duration { - self.device.activeVideoMaxFrameDuration = duration; + self.device.activeVideoMaxFrameDuration = duration; } -- (AVCaptureInput *)createInput:(NSError * _Nullable * _Nullable)error { +- (AVCaptureInput *)createInput:(NSError *_Nullable *_Nullable)error { return [AVCaptureDeviceInput deviceInputWithDevice:_device error:error]; } - @end diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m index 7b10f09109d4..0f909b2a9fa6 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m @@ -6,7 +6,7 @@ @implementation FLTDefaultDeviceOrientationProvider -- (UIDeviceOrientation)orientation { +- (UIDeviceOrientation)orientation { return [[UIDevice currentDevice] orientation]; } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h index 5af5163d2ef2..68ab3a861581 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h @@ -93,7 +93,8 @@ NS_ASSUME_NONNULL_BEGIN /// /// @param focusMode The focus mode that should be applied to the @captureDevice instance. /// @param captureDevice The AVCaptureDevice to which the @focusMode will be applied. -- (void)applyFocusMode:(FCPPlatformFocusMode)focusMode onDevice:(id)captureDevice; +- (void)applyFocusMode:(FCPPlatformFocusMode)focusMode + onDevice:(id)captureDevice; - (void)pausePreview; - (void)resumePreview; - (void)setDescriptionWhileRecording:(NSString *)cameraName diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h index 4e8d9d15cd8f..8d95cf02afe0 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h @@ -27,7 +27,8 @@ NS_ASSUME_NONNULL_BEGIN * @param outError The optional error. * @result A BOOL indicating whether the device was successfully locked for configuration. */ -- (BOOL)lockDevice:(id)captureDevice error:(NSError *_Nullable *_Nullable)outError; +- (BOOL)lockDevice:(id)captureDevice + error:(NSError *_Nullable *_Nullable)outError; /** * @method unlockDevice: @@ -59,7 +60,8 @@ NS_ASSUME_NONNULL_BEGIN * @param duration The frame duration. * @param captureDevice The capture device */ -- (void)setMinFrameDuration:(CMTime)duration onDevice:(id)captureDevice; +- (void)setMinFrameDuration:(CMTime)duration + onDevice:(id)captureDevice; /** * @method setMaxFrameDuration:onDevice: @@ -68,7 +70,8 @@ NS_ASSUME_NONNULL_BEGIN * @param duration The frame duration. * @param captureDevice The capture device */ -- (void)setMaxFrameDuration:(CMTime)duration onDevice:(id)captureDevice; +- (void)setMaxFrameDuration:(CMTime)duration + onDevice:(id)captureDevice; /** * @method assetWriterAudioInputWithOutputSettings: diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h index 65bf90a70b69..f643d335a4ca 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h @@ -3,8 +3,8 @@ // found in the LICENSE file. #import "FLTCam.h" -#import "FLTSavePhotoDelegate.h" #import "FLTCaptureDeviceControlling.h" +#import "FLTSavePhotoDelegate.h" /// Determines the video dimensions (width and height) for a given capture device format. /// Used in tests to mock CMVideoFormatDescriptionGetDimensions. diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h index 5603055865aa..370f0e5df10c 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h @@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)setExposurePointOfInterest:(CGPoint)point; - (float)minExposureTargetBias; - (float)maxExposureTargetBias; -- (void)setExposureTargetBias:(float)bias completionHandler:(void (^ _Nullable)(CMTime))handler; +- (void)setExposureTargetBias:(float)bias completionHandler:(void (^_Nullable)(CMTime))handler; - (BOOL)isExposureModeSupported:(AVCaptureExposureMode)mode; // Zoom @@ -61,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN - (CMTime)activeVideoMaxFrameDuration; - (void)setActiveVideoMaxFrameDuration:(CMTime)duration; -- (AVCaptureInput *)createInput:(NSError * _Nullable * _Nullable)error; +- (AVCaptureInput *)createInput:(NSError *_Nullable *_Nullable)error; @end diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/QueueUtils.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/QueueUtils.h index a7e22da716d0..e230a53508fa 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/QueueUtils.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/QueueUtils.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN /// Queue-specific context data to be associated with the capture session queue. -extern const char* FLTCaptureSessionQueueSpecific; +extern const char *FLTCaptureSessionQueueSpecific; /// Ensures the given block to be run on the main queue. /// If caller site is already on the main queue, the block will be run From c0b986c26a7107a5ce93b8501f43be15d737f92c Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Mon, 30 Dec 2024 13:40:35 +0100 Subject: [PATCH 04/16] Use DI for mocking dependencies --- .../camera/camera_avfoundation/CHANGELOG.md | 4 ++ .../ios/Runner.xcodeproj/project.pbxproj | 4 ++ .../ios/RunnerTests/CameraExposureTests.m | 13 +++++-- .../ios/RunnerTests/CameraFocusTests.m | 13 +++++-- .../ios/RunnerTests/CameraSettingsTests.m | 4 +- .../example/ios/RunnerTests/CameraTestUtils.h | 3 +- .../example/ios/RunnerTests/CameraTestUtils.m | 37 ++++++++++++------- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 6 ++- .../Sources/camera_avfoundation/FLTCam.m | 4 +- .../include/camera_avfoundation/FLTCam_Test.h | 2 + .../include/camera_avfoundation/QueueUtils.h | 2 +- .../camera/camera_avfoundation/pubspec.yaml | 2 +- 12 files changed, 64 insertions(+), 30 deletions(-) diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 51effb471121..4bca132957ff 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.18+1 + +* Introduces new protocols `FLTCaptureDeviceControlling` and `FLTDeviceOrientationProviding` + ## 0.9.18 * Adds API support query for image streaming. diff --git a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj index 04b0b3c45500..8dd444160cb9 100644 --- a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 7F56D0382D1EDDCE005676A5 /* CameraPermissionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */; }; 7F87E8022D01FD6F00A3549C /* MockCaptureDeviceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F87E8012D01FD5600A3549C /* MockCaptureDeviceController.m */; }; 7F87E80C2D0325D900A3549C /* MockDeviceOrientationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F87E80B2D0325D700A3549C /* MockDeviceOrientationProvider.m */; }; + 7FA99E592D22C75300582559 /* CameraExposureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FA99E582D22C75300582559 /* CameraExposureTests.m */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -82,6 +83,7 @@ 7F87E8032D02FF8C00A3549C /* MockCaptureDeviceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCaptureDeviceController.h; sourceTree = ""; }; 7F87E80A2D0325B200A3549C /* MockDeviceOrientationProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockDeviceOrientationProvider.h; sourceTree = ""; }; 7F87E80B2D0325D700A3549C /* MockDeviceOrientationProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockDeviceOrientationProvider.m; sourceTree = ""; }; + 7FA99E582D22C75300582559 /* CameraExposureTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraExposureTests.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -140,6 +142,7 @@ 7F87E8012D01FD5600A3549C /* MockCaptureDeviceController.m */, 7D5FCCD32AEF9D0200FB7108 /* CameraSettingsTests.m */, 03BB766A2665316900CE5A93 /* CameraFocusTests.m */, + 7FA99E582D22C75300582559 /* CameraExposureTests.m */, 03BB767226653ABE00CE5A93 /* CameraOrientationTests.m */, 03BB766C2665316900CE5A93 /* Info.plist */, 033B94BD269C40A200B4DF97 /* CameraMethodChannelTests.m */, @@ -462,6 +465,7 @@ 03BB766B2665316900CE5A93 /* CameraFocusTests.m in Sources */, 7F87E8022D01FD6F00A3549C /* MockCaptureDeviceController.m in Sources */, 7D5FCCD42AEF9D0200FB7108 /* CameraSettingsTests.m in Sources */, + 7FA99E592D22C75300582559 /* CameraExposureTests.m in Sources */, E487C86026D686A10034AC92 /* CameraPreviewPauseTests.m in Sources */, 7F87E80C2D0325D900A3549C /* MockDeviceOrientationProvider.m in Sources */, E071CF7427B31DE4006EF3BA /* FLTCamSampleBufferTests.m in Sources */, diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m index 28a5f7e1fcce..23f573581908 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m @@ -6,6 +6,7 @@ @import XCTest; @import AVFoundation; +#import "CameraTestUtils.h" #import "MockCaptureDeviceController.h" #import "MockDeviceOrientationProvider.h" @@ -18,12 +19,16 @@ @interface CameraExposureTests : XCTestCase @implementation CameraExposureTests - (void)setUp { - _camera = [[FLTCam alloc] init]; - _mockDevice = [[MockCaptureDeviceController alloc] init]; + MockCaptureDeviceController *mockDevice = [[MockCaptureDeviceController alloc] init]; _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; + _mockDevice = mockDevice; - [_camera setValue:_mockDevice forKey:@"captureDevice"]; - [_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"]; + _camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings( + nil, nil, nil, + ^id(void) { + return mockDevice; + }, + _mockDeviceOrientationProvider); } - (void)testSetExposurePointWithResult_SetsExposurePointOfInterest { diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m index f7d96c3aa75c..18fd29d89f3b 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m @@ -9,6 +9,7 @@ @import XCTest; @import AVFoundation; +#import "CameraTestUtils.h" #import "MockCaptureDeviceController.h" #import "MockDeviceOrientationProvider.h" @@ -21,12 +22,16 @@ @interface CameraFocusTests : XCTestCase @implementation CameraFocusTests - (void)setUp { - _camera = [[FLTCam alloc] init]; - _mockDevice = [[MockCaptureDeviceController alloc] init]; + MockCaptureDeviceController *mockDevice = [[MockCaptureDeviceController alloc] init]; + _mockDevice = mockDevice; _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; - [_camera setValue:_mockDevice forKey:@"captureDevice"]; - [_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"]; + _camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings( + nil, nil, nil, + ^id(void) { + return mockDevice; + }, + _mockDeviceOrientationProvider); } - (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus { diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraSettingsTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraSettingsTests.m index 9bed6bea4883..98e12020b59e 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraSettingsTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraSettingsTests.m @@ -144,7 +144,7 @@ - (void)testSettings_shouldPassConfigurationToCameraDeviceAndWriter { [[TestMediaSettingsAVWrapper alloc] initWithTestCase:self]; FLTCam *camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings( - dispatch_queue_create("test", NULL), settings, injectedWrapper, nil); + dispatch_queue_create("test", NULL), settings, injectedWrapper, nil, nil); // Expect FPS configuration is passed to camera device. [self waitForExpectations:@[ @@ -211,7 +211,7 @@ - (void)testSettings_ShouldSelectFormatWhichSupports60FPS { enableAudio:gTestEnableAudio]; FLTCam *camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings( - dispatch_queue_create("test", NULL), settings, nil, nil); + dispatch_queue_create("test", NULL), settings, nil, nil, nil); AVFrameRateRange *range = camera.captureDevice.activeFormat.videoSupportedFrameRateRanges[0]; XCTAssertLessThanOrEqual(range.minFrameRate, 60); diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.h index 2bbb56c51a79..008ba9df48f5 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.h +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.h @@ -20,7 +20,8 @@ extern FLTCam *_Nullable FLTCreateCamWithCaptureSessionQueueAndMediaSettings( dispatch_queue_t _Nullable captureSessionQueue, FCPPlatformMediaSettings *_Nullable mediaSettings, FLTCamMediaSettingsAVWrapper *_Nullable mediaSettingsAVWrapper, - CaptureDeviceFactory _Nullable captureDeviceFactory); + CaptureDeviceFactory _Nullable captureDeviceFactory, + id _Nullable deviceOrientationProvider); extern FLTCam *FLTCreateCamWithCaptureSessionQueue(dispatch_queue_t captureSessionQueue); diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m index f82bbf1aedc9..f10a3b122d7b 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m @@ -8,6 +8,8 @@ @import AVFoundation; @import camera_avfoundation; +#import "MockDeviceOrientationProvider.h" + static FCPPlatformMediaSettings *FCPGetDefaultMediaSettings( FCPPlatformResolutionPreset resolutionPreset) { return [FCPPlatformMediaSettings makeWithResolutionPreset:resolutionPreset @@ -18,13 +20,14 @@ } FLTCam *FLTCreateCamWithCaptureSessionQueue(dispatch_queue_t captureSessionQueue) { - return FLTCreateCamWithCaptureSessionQueueAndMediaSettings(captureSessionQueue, nil, nil, nil); + return FLTCreateCamWithCaptureSessionQueueAndMediaSettings(captureSessionQueue, nil, nil, nil, + nil); } FLTCam *FLTCreateCamWithCaptureSessionQueueAndMediaSettings( dispatch_queue_t captureSessionQueue, FCPPlatformMediaSettings *mediaSettings, - FLTCamMediaSettingsAVWrapper *mediaSettingsAVWrapper, - CaptureDeviceFactory captureDeviceFactory) { + FLTCamMediaSettingsAVWrapper *mediaSettingsAVWrapper, CaptureDeviceFactory captureDeviceFactory, + id deviceOrientationProvider) { if (!mediaSettings) { mediaSettings = FCPGetDefaultMediaSettings(FCPPlatformResolutionPresetMedium); } @@ -33,6 +36,10 @@ mediaSettingsAVWrapper = [[FLTCamMediaSettingsAVWrapper alloc] init]; } + if (!deviceOrientationProvider) { + deviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; + } + id inputMock = OCMClassMock([AVCaptureDeviceInput class]); OCMStub([inputMock deviceInputWithDevice:[OCMArg any] error:[OCMArg setTo:nil]]) .andReturn(inputMock); @@ -94,6 +101,7 @@ videoDimensionsForFormat:^CMVideoDimensions(AVCaptureDeviceFormat *format) { return CMVideoFormatDescriptionGetDimensions(format.formatDescription); } + deviceOrientationProvider:deviceOrientationProvider error:nil]; id captureVideoDataOutputMock = [OCMockObject niceMockForClass:[AVCaptureVideoDataOutput class]]; @@ -156,17 +164,18 @@ OCMStub([audioSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES); return [[FLTCam alloc] - initWithMediaSettings:FCPGetDefaultMediaSettings(resolutionPreset) - mediaSettingsAVWrapper:[[FLTCamMediaSettingsAVWrapper alloc] init] - orientation:UIDeviceOrientationPortrait - videoCaptureSession:captureSession - audioCaptureSession:audioSessionMock - captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL) - captureDeviceFactory:^id(void) { - return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDevice]; - } - videoDimensionsForFormat:videoDimensionsForFormat - error:nil]; + initWithMediaSettings:FCPGetDefaultMediaSettings(resolutionPreset) + mediaSettingsAVWrapper:[[FLTCamMediaSettingsAVWrapper alloc] init] + orientation:UIDeviceOrientationPortrait + videoCaptureSession:captureSession + audioCaptureSession:audioSessionMock + captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL) + captureDeviceFactory:^id(void) { + return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDevice]; + } + videoDimensionsForFormat:videoDimensionsForFormat + deviceOrientationProvider:[[MockDeviceOrientationProvider alloc] init] + error:nil]; } CMSampleBufferRef FLTCreateTestSampleBuffer(void) { diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 75a4f3abd7d0..c1bfb6ad376e 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -188,9 +188,11 @@ - (void)testCaptureToFile_handlesTorchMode { (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueueAndMediaSettings( - captureSessionQueue, nil, nil, ^id(void) { + captureSessionQueue, nil, nil, + ^id(void) { return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDeviceMock]; - }); + }, + nil); AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m index 34c5fcac41e8..4e0a02a364d2 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m @@ -153,6 +153,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName videoDimensionsForFormat:^CMVideoDimensions(AVCaptureDeviceFormat *format) { return CMVideoFormatDescriptionGetDimensions(format.formatDescription); } + deviceOrientationProvider:[[FLTDefaultDeviceOrientationProvider alloc] init] error:error]; } @@ -217,6 +218,7 @@ - (instancetype)initWithMediaSettings:(FCPPlatformMediaSettings *)mediaSettings captureSessionQueue:(dispatch_queue_t)captureSessionQueue captureDeviceFactory:(CaptureDeviceFactory)captureDeviceFactory videoDimensionsForFormat:(VideoDimensionsForFormat)videoDimensionsForFormat + deviceOrientationProvider:(id)deviceOrientationProvider error:(NSError **)error { self = [super init]; NSAssert(self, @"super init cannot be nil"); @@ -268,7 +270,7 @@ - (instancetype)initWithMediaSettings:(FCPPlatformMediaSettings *)mediaSettings _motionManager = [[CMMotionManager alloc] init]; [_motionManager startAccelerometerUpdates]; - _deviceOrientationProvider = [[FLTDefaultDeviceOrientationProvider alloc] init]; + _deviceOrientationProvider = deviceOrientationProvider; if (_mediaSettings.framesPerSecond) { // The frame rate can be changed only on a locked for configuration device. diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h index f643d335a4ca..7e27e31a8880 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h @@ -4,6 +4,7 @@ #import "FLTCam.h" #import "FLTCaptureDeviceControlling.h" +#import "FLTDeviceOrientationProviding.h" #import "FLTSavePhotoDelegate.h" /// Determines the video dimensions (width and height) for a given capture device format. @@ -75,6 +76,7 @@ typedef id (^CaptureDeviceFactory)(void); captureSessionQueue:(dispatch_queue_t)captureSessionQueue captureDeviceFactory:(CaptureDeviceFactory)captureDeviceFactory videoDimensionsForFormat:(VideoDimensionsForFormat)videoDimensionsForFormat + deviceOrientationProvider:(id)deviceOrientationProvider error:(NSError **)error; /// Start streaming images. diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/QueueUtils.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/QueueUtils.h index e230a53508fa..a7e22da716d0 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/QueueUtils.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/QueueUtils.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN /// Queue-specific context data to be associated with the capture session queue. -extern const char *FLTCaptureSessionQueueSpecific; +extern const char* FLTCaptureSessionQueueSpecific; /// Ensures the given block to be run on the main queue. /// If caller site is already on the main queue, the block will be run diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index dbfd772cb410..d5546a0fafb7 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -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.18 +version: 0.9.18+1 environment: sdk: ^3.4.0 From d24ca23d6f167345da0ec40354496175934953d9 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Mon, 30 Dec 2024 13:58:49 +0100 Subject: [PATCH 05/16] Fix CI --- .../Protocols/FLTCaptureDeviceControlling.m | 3 +++ .../Protocols/FLTDeviceOrientationProviding.m | 1 + 2 files changed, 4 insertions(+) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m index eaa4dfd250aa..89c72574a3d2 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m @@ -57,9 +57,12 @@ - (void)setTorchMode:(AVCaptureTorchMode)torchMode { self.device.torchMode = torchMode; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" - (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode { return [self.device isFlashModeSupported:mode]; } +#pragma clang diagnostic pop // Focus - (BOOL)isFocusPointOfInterestSupported { diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m index 0f909b2a9fa6..9592de778867 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m @@ -3,6 +3,7 @@ // found in the LICENSE file. #import "../include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h" +#import @implementation FLTDefaultDeviceOrientationProvider From efc892f88ae3125fae14d433fa0b01d00badf8ce Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Mon, 30 Dec 2024 14:10:51 +0100 Subject: [PATCH 06/16] Fix imports --- .../Protocols/FLTDeviceOrientationProviding.m | 1 - .../Protocols/FLTDeviceOrientationProviding.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m index 9592de778867..0f909b2a9fa6 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m @@ -3,7 +3,6 @@ // found in the LICENSE file. #import "../include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h" -#import @implementation FLTDefaultDeviceOrientationProvider diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h index e0b39f9b9e21..afdb607228d6 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@import AVFoundation; @import Foundation; +#import NS_ASSUME_NONNULL_BEGIN From 323ea395e27b9112ad11f82004f7223370cc5bc4 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Mon, 30 Dec 2024 14:21:18 +0100 Subject: [PATCH 07/16] Fix imports --- .../camera_avfoundation/include/camera_avfoundation/FLTCam.h | 2 +- .../camera_avfoundation/FLTCamMediaSettingsAVWrapper.h | 2 +- .../include/camera_avfoundation/FLTCam_Test.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h index 68ab3a861581..b51104fc138e 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h @@ -8,7 +8,7 @@ #import "CameraProperties.h" #import "FLTCamMediaSettingsAVWrapper.h" -#import "FLTCaptureDeviceControlling.h" +#import "Protocols/FLTCaptureDeviceControlling.h" #import "messages.g.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h index 8d95cf02afe0..1d59c5d7d88a 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h @@ -5,7 +5,7 @@ @import AVFoundation; @import Foundation; -#import "FLTCaptureDeviceControlling.h" +#import "Protocols/FLTCaptureDeviceControlling.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h index 7e27e31a8880..5db514cca45d 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h @@ -3,8 +3,8 @@ // found in the LICENSE file. #import "FLTCam.h" -#import "FLTCaptureDeviceControlling.h" -#import "FLTDeviceOrientationProviding.h" +#import "Protocols/FLTCaptureDeviceControlling.h" +#import "Protocols/FLTDeviceOrientationProviding.h" #import "FLTSavePhotoDelegate.h" /// Determines the video dimensions (width and height) for a given capture device format. From a3817a0c34243fa3e044da7cd549624515f4e6f1 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Mon, 30 Dec 2024 14:39:58 +0100 Subject: [PATCH 08/16] Another try to fix imports --- .../camera_avfoundation/include/camera_avfoundation/FLTCam.h | 3 ++- .../camera_avfoundation/FLTCamMediaSettingsAVWrapper.h | 2 +- .../include/camera_avfoundation/FLTCam_Test.h | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h index b51104fc138e..a2f150093528 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h @@ -6,9 +6,10 @@ @import Foundation; @import Flutter; +#import "FLTCaptureDeviceControlling.h" + #import "CameraProperties.h" #import "FLTCamMediaSettingsAVWrapper.h" -#import "Protocols/FLTCaptureDeviceControlling.h" #import "messages.g.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h index 1d59c5d7d88a..8d95cf02afe0 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h @@ -5,7 +5,7 @@ @import AVFoundation; @import Foundation; -#import "Protocols/FLTCaptureDeviceControlling.h" +#import "FLTCaptureDeviceControlling.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h index 5db514cca45d..7e27e31a8880 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h @@ -3,8 +3,8 @@ // found in the LICENSE file. #import "FLTCam.h" -#import "Protocols/FLTCaptureDeviceControlling.h" -#import "Protocols/FLTDeviceOrientationProviding.h" +#import "FLTCaptureDeviceControlling.h" +#import "FLTDeviceOrientationProviding.h" #import "FLTSavePhotoDelegate.h" /// Determines the video dimensions (width and height) for a given capture device format. From 3b6e455d0b62176b2c728d5cc44c4b09f8260798 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Mon, 30 Dec 2024 23:56:29 +0100 Subject: [PATCH 09/16] Change order in modulemap --- .../camera_avfoundation/include/CameraPlugin.modulemap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap index af0c9bee47fe..f7ba3069d6b0 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap @@ -5,6 +5,8 @@ framework module camera_avfoundation { module * { export * } explicit module Test { + header "FLTCaptureDeviceControlling.h" + header "FLTDeviceOrientationProviding.h" header "CameraPlugin_Test.h" header "CameraProperties.h" header "FLTCam.h" @@ -13,8 +15,6 @@ framework module camera_avfoundation { header "FLTThreadSafeEventChannel.h" header "FLTPermissionServicing.h" header "FLTCameraPermissionManager.h" - header "FLTCaptureDeviceControlling.h" - header "FLTDeviceOrientationProviding.h" header "QueueUtils.h" } } From defd0bae89110000281b25b5fa831ec6e766350b Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Tue, 31 Dec 2024 00:15:54 +0100 Subject: [PATCH 10/16] Add FLTCamMediaSettingsAVWrapper to module map --- .../Sources/camera_avfoundation/include/CameraPlugin.modulemap | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap index f7ba3069d6b0..6ba6e7b34c94 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap @@ -7,6 +7,7 @@ framework module camera_avfoundation { explicit module Test { header "FLTCaptureDeviceControlling.h" header "FLTDeviceOrientationProviding.h" + header "FLTCamMediaSettingsAVWrapper.h" header "CameraPlugin_Test.h" header "CameraProperties.h" header "FLTCam.h" From 0556d269971bf90e7661acb6ea791dc03f0d76a2 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Tue, 31 Dec 2024 11:42:51 +0100 Subject: [PATCH 11/16] Remove new protocols from modulemap --- .../Sources/camera_avfoundation/include/CameraPlugin.modulemap | 3 +-- .../camera_avfoundation/include/camera_avfoundation/FLTCam.h | 3 +-- .../include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h | 2 +- .../include/camera_avfoundation/FLTCam_Test.h | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap index 6ba6e7b34c94..df1f2e957ddf 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap @@ -6,15 +6,14 @@ framework module camera_avfoundation { explicit module Test { header "FLTCaptureDeviceControlling.h" + header "FLTPermissionServicing.h" header "FLTDeviceOrientationProviding.h" - header "FLTCamMediaSettingsAVWrapper.h" header "CameraPlugin_Test.h" header "CameraProperties.h" header "FLTCam.h" header "FLTCam_Test.h" header "FLTSavePhotoDelegate_Test.h" header "FLTThreadSafeEventChannel.h" - header "FLTPermissionServicing.h" header "FLTCameraPermissionManager.h" header "QueueUtils.h" } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h index a2f150093528..959f92fdcd76 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h @@ -6,11 +6,10 @@ @import Foundation; @import Flutter; -#import "FLTCaptureDeviceControlling.h" - #import "CameraProperties.h" #import "FLTCamMediaSettingsAVWrapper.h" #import "messages.g.h" +#import "Protocols/FLTCaptureDeviceControlling.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h index 8d95cf02afe0..1d59c5d7d88a 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h @@ -5,7 +5,7 @@ @import AVFoundation; @import Foundation; -#import "FLTCaptureDeviceControlling.h" +#import "Protocols/FLTCaptureDeviceControlling.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h index 7e27e31a8880..558d3e777835 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h @@ -3,9 +3,9 @@ // found in the LICENSE file. #import "FLTCam.h" -#import "FLTCaptureDeviceControlling.h" #import "FLTDeviceOrientationProviding.h" #import "FLTSavePhotoDelegate.h" +#import "Protocols/FLTCaptureDeviceControlling.h" /// Determines the video dimensions (width and height) for a given capture device format. /// Used in tests to mock CMVideoFormatDescriptionGetDimensions. From 09241f414a1e6e16384d5b0663d748e283e27755 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Tue, 31 Dec 2024 12:21:55 +0100 Subject: [PATCH 12/16] Add header search path --- .../camera_avfoundation/ios/camera_avfoundation/Package.swift | 1 + .../camera_avfoundation/include/camera_avfoundation/FLTCam.h | 2 +- .../include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h | 2 +- .../include/camera_avfoundation/FLTCam_Test.h | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Package.swift b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Package.swift index 48050b6b788b..3ea113b3a119 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Package.swift +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Package.swift @@ -25,6 +25,7 @@ let package = Package( ], cSettings: [ .headerSearchPath("include/camera_avfoundation") + .headerSearchPath("include/camera_avfoundation/Protocols") ] ) ] diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h index 959f92fdcd76..80e54b0e0d12 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h @@ -9,7 +9,7 @@ #import "CameraProperties.h" #import "FLTCamMediaSettingsAVWrapper.h" #import "messages.g.h" -#import "Protocols/FLTCaptureDeviceControlling.h" +#import "FLTCaptureDeviceControlling.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h index 1d59c5d7d88a..8d95cf02afe0 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h @@ -5,7 +5,7 @@ @import AVFoundation; @import Foundation; -#import "Protocols/FLTCaptureDeviceControlling.h" +#import "FLTCaptureDeviceControlling.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h index 558d3e777835..7e27e31a8880 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam_Test.h @@ -3,9 +3,9 @@ // found in the LICENSE file. #import "FLTCam.h" +#import "FLTCaptureDeviceControlling.h" #import "FLTDeviceOrientationProviding.h" #import "FLTSavePhotoDelegate.h" -#import "Protocols/FLTCaptureDeviceControlling.h" /// Determines the video dimensions (width and height) for a given capture device format. /// Used in tests to mock CMVideoFormatDescriptionGetDimensions. From fa8f495b511b78b28878c092601ada87fa27d7eb Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Tue, 31 Dec 2024 12:27:02 +0100 Subject: [PATCH 13/16] Fix formatting --- .../camera_avfoundation/ios/camera_avfoundation/Package.swift | 1 - .../camera_avfoundation/include/CameraPlugin.modulemap | 4 ++-- .../camera_avfoundation/include/camera_avfoundation/FLTCam.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Package.swift b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Package.swift index 3ea113b3a119..48050b6b788b 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Package.swift +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Package.swift @@ -25,7 +25,6 @@ let package = Package( ], cSettings: [ .headerSearchPath("include/camera_avfoundation") - .headerSearchPath("include/camera_avfoundation/Protocols") ] ) ] diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap index df1f2e957ddf..4f2c934be24d 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap @@ -5,9 +5,9 @@ framework module camera_avfoundation { module * { export * } explicit module Test { - header "FLTCaptureDeviceControlling.h" + header "Protocols/FLTCaptureDeviceControlling.h" + header "Protocols/FLTDeviceOrientationProviding.h" header "FLTPermissionServicing.h" - header "FLTDeviceOrientationProviding.h" header "CameraPlugin_Test.h" header "CameraProperties.h" header "FLTCam.h" diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h index 80e54b0e0d12..68ab3a861581 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h @@ -8,8 +8,8 @@ #import "CameraProperties.h" #import "FLTCamMediaSettingsAVWrapper.h" -#import "messages.g.h" #import "FLTCaptureDeviceControlling.h" +#import "messages.g.h" NS_ASSUME_NONNULL_BEGIN From d4c4f3a299c9b8b67184b76cbd89fc45c6822a39 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Thu, 2 Jan 2025 10:04:21 +0100 Subject: [PATCH 14/16] Flatten the structure --- .../camera_avfoundation/Sources/camera_avfoundation/FLTCam.m | 4 ++-- .../camera_avfoundation/FLTCamMediaSettingsAVWrapper.m | 2 +- .../{Protocols => }/FLTCaptureDeviceControlling.m | 2 +- .../{Protocols => }/FLTDeviceOrientationProviding.m | 2 +- .../camera_avfoundation/include/CameraPlugin.modulemap | 4 ++-- .../{Protocols => }/FLTCaptureDeviceControlling.h | 0 .../{Protocols => }/FLTDeviceOrientationProviding.h | 0 7 files changed, 7 insertions(+), 7 deletions(-) rename packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/{Protocols => }/FLTCaptureDeviceControlling.m (97%) rename packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/{Protocols => }/FLTDeviceOrientationProviding.m (79%) rename packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/{Protocols => }/FLTCaptureDeviceControlling.h (100%) rename packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/{Protocols => }/FLTDeviceOrientationProviding.h (100%) diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m index 4e0a02a364d2..03474c5435a0 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m @@ -9,10 +9,10 @@ @import Flutter; #import +#import "./include/camera_avfoundation/FLTCaptureDeviceControlling.h" +#import "./include/camera_avfoundation/FLTDeviceOrientationProviding.h" #import "./include/camera_avfoundation/FLTSavePhotoDelegate.h" #import "./include/camera_avfoundation/FLTThreadSafeEventChannel.h" -#import "./include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h" -#import "./include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h" #import "./include/camera_avfoundation/QueueUtils.h" #import "./include/camera_avfoundation/messages.g.h" diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m index 0ecf89a724ce..21a0d9a68eeb 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCamMediaSettingsAVWrapper.m @@ -3,7 +3,7 @@ // found in the LICENSE file. #import "./include/camera_avfoundation/FLTCamMediaSettingsAVWrapper.h" -#import "./include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h" +#import "./include/camera_avfoundation/FLTCaptureDeviceControlling.h" @implementation FLTCamMediaSettingsAVWrapper diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCaptureDeviceControlling.m similarity index 97% rename from packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m rename to packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCaptureDeviceControlling.m index 89c72574a3d2..658e0a0fedb4 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCaptureDeviceControlling.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "../include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h" +#import "./include/camera_avfoundation/FLTCaptureDeviceControlling.h" @interface FLTDefaultCaptureDeviceController () @property(nonatomic, strong) AVCaptureDevice *device; diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTDeviceOrientationProviding.m similarity index 79% rename from packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m rename to packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTDeviceOrientationProviding.m index 0f909b2a9fa6..5419eb0a3588 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTDeviceOrientationProviding.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "../include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h" +#import "./include/camera_avfoundation/FLTDeviceOrientationProviding.h" @implementation FLTDefaultDeviceOrientationProvider diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap index 4f2c934be24d..899a43a3cab1 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/CameraPlugin.modulemap @@ -5,8 +5,8 @@ framework module camera_avfoundation { module * { export * } explicit module Test { - header "Protocols/FLTCaptureDeviceControlling.h" - header "Protocols/FLTDeviceOrientationProviding.h" + header "FLTCaptureDeviceControlling.h" + header "FLTDeviceOrientationProviding.h" header "FLTPermissionServicing.h" header "CameraPlugin_Test.h" header "CameraProperties.h" diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h similarity index 100% rename from packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTCaptureDeviceControlling.h rename to packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTDeviceOrientationProviding.h similarity index 100% rename from packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/Protocols/FLTDeviceOrientationProviding.h rename to packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTDeviceOrientationProviding.h From f58fb9bdd482f6a9260848df09f64ea85827f187 Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Thu, 16 Jan 2025 13:51:15 +0100 Subject: [PATCH 15/16] Add comments and use the same names for protocol properties --- packages/camera/camera_avfoundation/CHANGELOG.md | 2 +- .../example/ios/RunnerTests/CameraExposureTests.m | 4 ++-- .../example/ios/RunnerTests/CameraFocusTests.m | 4 ++-- .../ios/RunnerTests/MockCaptureDeviceController.h | 4 ++-- .../ios/RunnerTests/MockCaptureDeviceController.m | 4 ++-- .../ios/RunnerTests/MockDeviceOrientationProvider.m | 4 ++-- .../Sources/camera_avfoundation/FLTCam.m | 8 ++++---- .../camera_avfoundation/FLTCaptureDeviceControlling.m | 8 ++++---- .../camera_avfoundation/FLTCaptureDeviceControlling.h | 11 +++++++++-- .../FLTDeviceOrientationProviding.h | 7 +++++++ 10 files changed, 35 insertions(+), 21 deletions(-) diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 4bca132957ff..d40aeca0e555 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.9.18+1 -* Introduces new protocols `FLTCaptureDeviceControlling` and `FLTDeviceOrientationProviding` +* Refactors implementations to reduce usage of OCMock in internal testing. ## 0.9.18 diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m index 23f573581908..30de3182c33e 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.m @@ -35,7 +35,7 @@ - (void)testSetExposurePointWithResult_SetsExposurePointOfInterest { // UI is currently in landscape left orientation _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Exposure point of interest is supported - _mockDevice.isExposurePointOfInterestSupported = YES; + _mockDevice.exposurePointOfInterestSupported = YES; // Verify the focus point of interest has been set __block CGPoint setPoint = CGPointZero; @@ -62,7 +62,7 @@ - (void)testSetExposurePoint_WhenNotSupported_ReturnsError { // UI is currently in landscape left orientation _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Exposure point of interest is not supported - _mockDevice.isExposurePointOfInterestSupported = NO; + _mockDevice.exposurePointOfInterestSupported = NO; XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"]; diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m index 18fd29d89f3b..63be762f5296 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m @@ -139,7 +139,7 @@ - (void)testSetFocusPointWithResult_SetsFocusPointOfInterest { // UI is currently in landscape left orientation _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Focus point of interest is supported - _mockDevice.isFocusPointOfInterestSupported = YES; + _mockDevice.focusPointOfInterestSupported = YES; __block BOOL setFocusPointOfInterestCalled = NO; _mockDevice.setFocusPointOfInterestStub = ^(CGPoint point) { @@ -161,7 +161,7 @@ - (void)testSetFocusPoint_WhenNotSupported_ReturnsError { // UI is currently in landscape left orientation _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; // Exposure point of interest is not supported - _mockDevice.isFocusPointOfInterestSupported = NO; + _mockDevice.focusPointOfInterestSupported = NO; XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"]; diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h index af28d652734a..884755b0fe32 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h @@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, assign) BOOL flashModeSupported; // Focus -@property(nonatomic, assign) BOOL isFocusPointOfInterestSupported; +@property(nonatomic, assign) BOOL focusPointOfInterestSupported; @property(nonatomic, copy) BOOL (^isFocusModeSupportedStub)(AVCaptureFocusMode mode); @property(nonatomic, assign) AVCaptureFocusMode focusMode; @property(nonatomic, copy) void (^setFocusModeStub)(AVCaptureFocusMode mode); @@ -36,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy) void (^setFocusPointOfInterestStub)(CGPoint point); // Exposure -@property(nonatomic, assign) BOOL isExposurePointOfInterestSupported; +@property(nonatomic, assign) BOOL exposurePointOfInterestSupported; @property(nonatomic, assign) AVCaptureExposureMode exposureMode; @property(nonatomic, assign) BOOL exposureModeSupported; @property(nonatomic, copy) void (^setExposureModeStub)(AVCaptureExposureMode mode); diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m index cc89bb85abf8..011ec337a876 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "MockCaptureDeviceController.h" + @import camera_avfoundation; #if __has_include() @import camera_avfoundation.Test; #endif @import AVFoundation; -#import "MockCaptureDeviceController.h" - @implementation MockCaptureDeviceController - (void)setActiveFormat:(AVCaptureDeviceFormat *)format { diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.m index 963cb7e96ff9..730572b315ac 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockDeviceOrientationProvider.m @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "MockDeviceOrientationProvider.h" + @import camera_avfoundation; #if __has_include() @import camera_avfoundation.Test; #endif @import AVFoundation; -#import "MockDeviceOrientationProvider.h" - @implementation MockDeviceOrientationProvider @end diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m index 03474c5435a0..577460b1a868 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCam.m @@ -353,8 +353,8 @@ - (void)reportInitializationState { height:self.previewSize.height] exposureMode:self.exposureMode focusMode:self.focusMode - exposurePointSupported:self.captureDevice.isExposurePointOfInterestSupported - focusPointSupported:self.captureDevice.isFocusPointOfInterestSupported]; + exposurePointSupported:self.captureDevice.exposurePointOfInterestSupported + focusPointSupported:self.captureDevice.focusPointOfInterestSupported]; __weak typeof(self) weakSelf = self; FLTEnsureToRunOnMainQueue(^{ @@ -1158,7 +1158,7 @@ - (CGPoint)CGPointForPoint:(nonnull FCPPlatformPoint *)point - (void)setExposurePoint:(FCPPlatformPoint *)point withCompletion:(void (^)(FlutterError *_Nullable))completion { - if (!_captureDevice.isExposurePointOfInterestSupported) { + if (!_captureDevice.exposurePointOfInterestSupported) { completion([FlutterError errorWithCode:@"setExposurePointFailed" message:@"Device does not have exposure point capabilities" details:nil]); @@ -1180,7 +1180,7 @@ - (void)setExposurePoint:(FCPPlatformPoint *)point - (void)setFocusPoint:(FCPPlatformPoint *)point withCompletion:(void (^)(FlutterError *_Nullable))completion { - if (!_captureDevice.isFocusPointOfInterestSupported) { + if (!_captureDevice.focusPointOfInterestSupported) { completion([FlutterError errorWithCode:@"setFocusPointFailed" message:@"Device does not have focus point capabilities" details:nil]); diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCaptureDeviceControlling.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCaptureDeviceControlling.m index 658e0a0fedb4..95d3f80519fc 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCaptureDeviceControlling.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCaptureDeviceControlling.m @@ -65,8 +65,8 @@ - (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode { #pragma clang diagnostic pop // Focus -- (BOOL)isFocusPointOfInterestSupported { - return self.device.isFocusPointOfInterestSupported; +- (BOOL)focusPointOfInterestSupported { + return self.device.focusPointOfInterestSupported; } - (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode { @@ -82,8 +82,8 @@ - (void)setFocusPointOfInterest:(CGPoint)point { } // Exposure -- (BOOL)isExposurePointOfInterestSupported { - return self.device.isExposurePointOfInterestSupported; +- (BOOL)exposurePointOfInterestSupported { + return self.device.exposurePointOfInterestSupported; } - (void)setExposureMode:(AVCaptureExposureMode)exposureMode { diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h index 370f0e5df10c..c10dc9eb9338 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h @@ -7,6 +7,8 @@ NS_ASSUME_NONNULL_BEGIN +/// A protocol which is a direct passthrough to AVCaptureDevice. +/// It exists to allow replacing AVCaptureDevice in tests. @protocol FLTCaptureDeviceControlling // Position/Orientation @@ -26,13 +28,13 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode; // Focus -- (BOOL)isFocusPointOfInterestSupported; +- (BOOL)focusPointOfInterestSupported; - (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode; - (void)setFocusMode:(AVCaptureFocusMode)focusMode; - (void)setFocusPointOfInterest:(CGPoint)point; // Exposure -- (BOOL)isExposurePointOfInterestSupported; +- (BOOL)exposurePointOfInterestSupported; - (void)setExposureMode:(AVCaptureExposureMode)exposureMode; - (void)setExposurePointOfInterest:(CGPoint)point; - (float)minExposureTargetBias; @@ -65,8 +67,13 @@ NS_ASSUME_NONNULL_BEGIN @end +/// A default implementation of FLTCaptureDeviceControlling protocol which +/// wraps an instance of AVCaptureDevice. @interface FLTDefaultCaptureDeviceController : NSObject + +/// Initializes the controller with the given device. - (instancetype)initWithDevice:(AVCaptureDevice *)device; + @end NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTDeviceOrientationProviding.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTDeviceOrientationProviding.h index afdb607228d6..0a9b1a746187 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTDeviceOrientationProviding.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTDeviceOrientationProviding.h @@ -7,10 +7,17 @@ NS_ASSUME_NONNULL_BEGIN +/// A protocol which provides the current device orientation. +/// It exists to allow replacing UIDevice in tests. @protocol FLTDeviceOrientationProviding + +/// Returns the physical orientation of the device. - (UIDeviceOrientation)orientation; + @end +/// A default implementation of FLTDeviceOrientationProviding which uses orientation +/// of the current device from UIDevice. @interface FLTDefaultDeviceOrientationProvider : NSObject @end From e3f1afd6601ffff3622b8a94b098885da7b0562b Mon Sep 17 00:00:00 2001 From: Marcin Chudy Date: Thu, 16 Jan 2025 15:14:41 +0100 Subject: [PATCH 16/16] Remove logic from mock methods --- .../RunnerTests/MockCaptureDeviceController.h | 29 +++++++++++++++++++ .../RunnerTests/MockCaptureDeviceController.m | 11 +------ .../FLTCaptureDeviceControlling.h | 2 +- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h index 884755b0fe32..905109811c89 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.h @@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN // Format/Configuration @property(nonatomic, strong) AVCaptureDeviceFormat *activeFormat; @property(nonatomic, strong) NSArray *formats; +/// Overrides the default implementation of setting active format. +/// @param format The format being set @property(nonatomic, copy) void (^setActiveFormatStub)(AVCaptureDeviceFormat *format); // Flash/Torch @@ -24,26 +26,42 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, assign) BOOL hasTorch; @property(nonatomic, assign) BOOL isTorchAvailable; @property(nonatomic, assign) AVCaptureTorchMode torchMode; +/// Overrides the default implementation of setting torch mode. +/// @param mode The torch mode being set @property(nonatomic, copy) void (^setTorchModeStub)(AVCaptureTorchMode mode); @property(nonatomic, assign) BOOL flashModeSupported; // Focus @property(nonatomic, assign) BOOL focusPointOfInterestSupported; +/// Overrides the default implementation of checking if focus mode is supported. +/// @param mode The focus mode to check +/// @return Whether the focus mode is supported @property(nonatomic, copy) BOOL (^isFocusModeSupportedStub)(AVCaptureFocusMode mode); @property(nonatomic, assign) AVCaptureFocusMode focusMode; +/// Overrides the default implementation of setting focus mode. +/// @param mode The focus mode being set @property(nonatomic, copy) void (^setFocusModeStub)(AVCaptureFocusMode mode); @property(nonatomic, assign) CGPoint focusPointOfInterest; +/// Overrides the default implementation of setting focus point of interest. +/// @param point The focus point being set @property(nonatomic, copy) void (^setFocusPointOfInterestStub)(CGPoint point); // Exposure @property(nonatomic, assign) BOOL exposurePointOfInterestSupported; @property(nonatomic, assign) AVCaptureExposureMode exposureMode; @property(nonatomic, assign) BOOL exposureModeSupported; +/// Overrides the default implementation of setting exposure mode. +/// @param mode The exposure mode being set @property(nonatomic, copy) void (^setExposureModeStub)(AVCaptureExposureMode mode); @property(nonatomic, assign) CGPoint exposurePointOfInterest; +/// Override the default implementation of setting exposure point of interest. +/// @param point The exposure point being set @property(nonatomic, copy) void (^setExposurePointOfInterestStub)(CGPoint point); @property(nonatomic, assign) float minExposureTargetBias; @property(nonatomic, assign) float maxExposureTargetBias; +/// Overrides the default implementation of setting exposure target bias. +/// @param bias The exposure bias being set +/// @param handler The completion handler to be called @property(nonatomic, copy) void (^setExposureTargetBiasStub) (float bias, void (^_Nullable handler)(CMTime)); @@ -51,6 +69,8 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, assign) float maxAvailableVideoZoomFactor; @property(nonatomic, assign) float minAvailableVideoZoomFactor; @property(nonatomic, assign) float videoZoomFactor; +/// Overrides the default implementation of setting video zoom factor. +/// @param factor The zoom factor being set @property(nonatomic, copy) void (^setVideoZoomFactorStub)(float factor); // Camera Properties @@ -60,17 +80,26 @@ NS_ASSUME_NONNULL_BEGIN // Configuration Lock @property(nonatomic, assign) BOOL shouldFailConfiguration; +/// Overrides the default implementation of locking device for configuration. +/// @param error Error pointer to be set if lock fails @property(nonatomic, copy) void (^lockForConfigurationStub)(NSError **error); +/// Overrides the default implementation of unlocking device configuration. @property(nonatomic, copy) void (^unlockForConfigurationStub)(void); // Frame Duration @property(nonatomic, assign) CMTime activeVideoMinFrameDuration; @property(nonatomic, assign) CMTime activeVideoMaxFrameDuration; +/// Overrides the default implementation of setting minimum frame duration. +/// @param duration The minimum frame duration being set @property(nonatomic, copy) void (^setActiveVideoMinFrameDurationStub)(CMTime duration); +/// Overrides the default implementation of setting maximum frame duration. +/// @param duration The maximum frame duration being set @property(nonatomic, copy) void (^setActiveVideoMaxFrameDurationStub)(CMTime duration); // Input Creation @property(nonatomic, strong) AVCaptureInput *inputToReturn; +/// Overrides the default implementation of creating capture input. +/// @param error Error pointer to be set if creation fails @property(nonatomic, copy) void (^createInputStub)(NSError **error); @end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m index 011ec337a876..6691b7d76942 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/MockCaptureDeviceController.m @@ -1,3 +1,4 @@ + // 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. @@ -13,7 +14,6 @@ @implementation MockCaptureDeviceController - (void)setActiveFormat:(AVCaptureDeviceFormat *)format { - _activeFormat = format; if (self.setActiveFormatStub) { self.setActiveFormatStub(format); } @@ -24,7 +24,6 @@ - (BOOL)isFlashModeSupported:(AVCaptureFlashMode)mode { } - (void)setTorchMode:(AVCaptureTorchMode)mode { - _torchMode = mode; if (self.setTorchModeStub) { self.setTorchModeStub(mode); } @@ -38,21 +37,18 @@ - (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode { } - (void)setFocusMode:(AVCaptureFocusMode)mode { - _focusMode = mode; if (self.setFocusModeStub) { self.setFocusModeStub(mode); } } - (void)setFocusPointOfInterest:(CGPoint)point { - _focusPointOfInterest = point; if (self.setFocusPointOfInterestStub) { self.setFocusPointOfInterestStub(point); } } - (void)setExposureMode:(AVCaptureExposureMode)mode { - _exposureMode = mode; if (self.setExposureModeStub) { self.setExposureModeStub(mode); } @@ -68,13 +64,10 @@ - (void)setExposurePointOfInterest:(CGPoint)point { - (void)setExposureTargetBias:(float)bias completionHandler:(void (^)(CMTime))handler { if (self.setExposureTargetBiasStub) { self.setExposureTargetBiasStub(bias, handler); - } else if (handler) { - handler(kCMTimeZero); } } - (void)setVideoZoomFactor:(float)factor { - _videoZoomFactor = factor; if (self.setVideoZoomFactorStub) { self.setVideoZoomFactorStub(factor); } @@ -101,14 +94,12 @@ - (void)unlockForConfiguration { } - (void)setActiveVideoMinFrameDuration:(CMTime)duration { - _activeVideoMinFrameDuration = duration; if (self.setActiveVideoMinFrameDurationStub) { self.setActiveVideoMinFrameDurationStub(duration); } } - (void)setActiveVideoMaxFrameDuration:(CMTime)duration { - _activeVideoMaxFrameDuration = duration; if (self.setActiveVideoMaxFrameDurationStub) { self.setActiveVideoMaxFrameDurationStub(duration); } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h index c10dc9eb9338..38f79408959f 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCaptureDeviceControlling.h @@ -68,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN @end /// A default implementation of FLTCaptureDeviceControlling protocol which -/// wraps an instance of AVCaptureDevice. +/// wraps an instance of AVCaptureDevice. @interface FLTDefaultCaptureDeviceController : NSObject /// Initializes the controller with the given device.