Merge branch 'master' into ci
# Conflicts: # .github/workflows/flutter.yml
Showing
3 changed files
with
91 additions
and
23 deletions
| @@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
| 7 | release-please: | 7 | release-please: |
| 8 | runs-on: ubuntu-latest | 8 | runs-on: ubuntu-latest |
| 9 | steps: | 9 | steps: |
| 10 | - - uses: GoogleCloudPlatform/release-please-action@v3.7.13 | 10 | + - uses: GoogleCloudPlatform/release-please-action@v4.0.1 |
| 11 | with: | 11 | with: |
| 12 | token: ${{ secrets.GITHUB_TOKEN }} | 12 | token: ${{ secrets.GITHUB_TOKEN }} |
| 13 | release-type: simple | 13 | release-type: simple |
| @@ -69,6 +69,43 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -69,6 +69,43 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 69 | super.init() | 69 | super.init() |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | + /// Get the default camera device for the given `position`. | ||
| 73 | + /// | ||
| 74 | + /// This function selects the most appropriate camera, when it is available. | ||
| 75 | + private func getDefaultCameraDevice(position: AVCaptureDevice.Position) -> AVCaptureDevice? { | ||
| 76 | + if #available(iOS 13.0, *) { | ||
| 77 | + // Find the built-in Triple Camera, if it exists. | ||
| 78 | + if let device = AVCaptureDevice.default(.builtInTripleCamera, | ||
| 79 | + for: .video, | ||
| 80 | + position: position) { | ||
| 81 | + return device | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + // Find the built-in Dual-Wide Camera, if it exists. | ||
| 85 | + if let device = AVCaptureDevice.default(.builtInDualWideCamera, | ||
| 86 | + for: .video, | ||
| 87 | + position: position) { | ||
| 88 | + return device | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + // Find the built-in Dual Camera, if it exists. | ||
| 93 | + if let device = AVCaptureDevice.default(.builtInDualCamera, | ||
| 94 | + for: .video, | ||
| 95 | + position: position) { | ||
| 96 | + return device | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + // Find the built-in Wide-Angle Camera, if it exists. | ||
| 100 | + if let device = AVCaptureDevice.default(.builtInWideAngleCamera, | ||
| 101 | + for: .video, | ||
| 102 | + position: position) { | ||
| 103 | + return device | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + return nil | ||
| 107 | + } | ||
| 108 | + | ||
| 72 | /// Check if we already have camera permission. | 109 | /// Check if we already have camera permission. |
| 73 | func checkPermission() -> Int { | 110 | func checkPermission() -> Int { |
| 74 | let status = AVCaptureDevice.authorizationStatus(for: .video) | 111 | let status = AVCaptureDevice.authorizationStatus(for: .video) |
| @@ -146,11 +183,7 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -146,11 +183,7 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 146 | textureId = registry?.register(self) | 183 | textureId = registry?.register(self) |
| 147 | 184 | ||
| 148 | // Open the camera device | 185 | // Open the camera device |
| 149 | - if #available(iOS 13.0, *) { | ||
| 150 | - device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInTripleCamera, .builtInDualWideCamera, .builtInDualCamera, .builtInWideAngleCamera], mediaType: .video, position: cameraPosition).devices.first | ||
| 151 | - } else { | ||
| 152 | - device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInWideAngleCamera], mediaType: .video, position: cameraPosition).devices.first | ||
| 153 | - } | 186 | + device = getDefaultCameraDevice(position: cameraPosition) |
| 154 | 187 | ||
| 155 | if (device == nil) { | 188 | if (device == nil) { |
| 156 | throw MobileScannerError.noCamera | 189 | throw MobileScannerError.noCamera |
| @@ -215,26 +248,35 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -215,26 +248,35 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 215 | 248 | ||
| 216 | backgroundQueue.async { | 249 | backgroundQueue.async { |
| 217 | self.captureSession.startRunning() | 250 | self.captureSession.startRunning() |
| 218 | - | ||
| 219 | - // Turn on the flashlight if requested, | ||
| 220 | - // but after the capture session started. | 251 | + |
| 252 | + // After the capture session started, turn on the torch (if requested) | ||
| 253 | + // and reset the zoom scale back to the default. | ||
| 254 | + // Ensure that these adjustments are done on the main DispatchQueue, | ||
| 255 | + // as they interact with the hardware camera. | ||
| 221 | if (torch) { | 256 | if (torch) { |
| 257 | + DispatchQueue.main.async { | ||
| 258 | + do { | ||
| 259 | + try self.toggleTorch(.on) | ||
| 260 | + } catch { | ||
| 261 | + // If the torch does not turn on, | ||
| 262 | + // continue with the capture session anyway. | ||
| 263 | + } | ||
| 264 | + } | ||
| 265 | + } | ||
| 266 | + | ||
| 267 | + DispatchQueue.main.async { | ||
| 222 | do { | 268 | do { |
| 223 | - try self.toggleTorch(.on) | 269 | + try self.resetScale() |
| 224 | } catch { | 270 | } catch { |
| 225 | - // If the torch does not turn on, | 271 | + // If the zoom scale could not be reset, |
| 226 | // continue with the capture session anyway. | 272 | // continue with the capture session anyway. |
| 227 | } | 273 | } |
| 228 | } | 274 | } |
| 229 | 275 | ||
| 230 | - do { | ||
| 231 | - try self.resetScale() | ||
| 232 | - } catch { | ||
| 233 | - // If the zoom scale could not be reset, | ||
| 234 | - // continue with the capture session anyway. | ||
| 235 | - } | ||
| 236 | - | ||
| 237 | if let device = self.device { | 276 | if let device = self.device { |
| 277 | + // When querying the dimensions of the camera, | ||
| 278 | + // stay on the background thread, | ||
| 279 | + // as this does not change the configuration of the hardware camera. | ||
| 238 | let dimensions = CMVideoFormatDescriptionGetDimensions( | 280 | let dimensions = CMVideoFormatDescriptionGetDimensions( |
| 239 | device.activeFormat.formatDescription) | 281 | device.activeFormat.formatDescription) |
| 240 | let hasTorch = device.hasTorch | 282 | let hasTorch = device.hasTorch |
| @@ -277,12 +319,18 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -277,12 +319,18 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 277 | device = nil | 319 | device = nil |
| 278 | } | 320 | } |
| 279 | 321 | ||
| 280 | - /// Toggle the flashlight between on and off. | 322 | + /// Set the torch mode. |
| 323 | + /// | ||
| 324 | + /// This method should be called on the main DispatchQueue. | ||
| 281 | func toggleTorch(_ torch: AVCaptureDevice.TorchMode) throws { | 325 | func toggleTorch(_ torch: AVCaptureDevice.TorchMode) throws { |
| 282 | - if (device == nil || !device.hasTorch || !device.isTorchAvailable) { | 326 | + guard let device = self.device else { |
| 283 | return | 327 | return |
| 284 | } | 328 | } |
| 285 | - | 329 | + |
| 330 | + if (!device.hasTorch || !device.isTorchAvailable || !device.isTorchModeSupported(torch)) { | ||
| 331 | + return | ||
| 332 | + } | ||
| 333 | + | ||
| 286 | if (device.torchMode != torch) { | 334 | if (device.torchMode != torch) { |
| 287 | try device.lockForConfiguration() | 335 | try device.lockForConfiguration() |
| 288 | device.torchMode = torch | 336 | device.torchMode = torch |
| @@ -61,6 +61,10 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | @@ -61,6 +61,10 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | ||
| 61 | start(call, result) | 61 | start(call, result) |
| 62 | case "torch": | 62 | case "torch": |
| 63 | toggleTorch(call, result) | 63 | toggleTorch(call, result) |
| 64 | + case "setScale": | ||
| 65 | + setScale(call, result) | ||
| 66 | + case "resetScale": | ||
| 67 | + resetScale(call, result) | ||
| 64 | // case "analyze": | 68 | // case "analyze": |
| 65 | // switchAnalyzeMode(call, result) | 69 | // switchAnalyzeMode(call, result) |
| 66 | case "stop": | 70 | case "stop": |
| @@ -320,7 +324,11 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | @@ -320,7 +324,11 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | ||
| 320 | 324 | ||
| 321 | // TODO: this method should be removed when iOS and MacOS share their implementation. | 325 | // TODO: this method should be removed when iOS and MacOS share their implementation. |
| 322 | private func toggleTorchInternal(_ torch: AVCaptureDevice.TorchMode) throws { | 326 | private func toggleTorchInternal(_ torch: AVCaptureDevice.TorchMode) throws { |
| 323 | - if (device == nil || !device.hasTorch) { | 327 | + guard let device = self.device else { |
| 328 | + return | ||
| 329 | + } | ||
| 330 | + | ||
| 331 | + if (!device.hasTorch || !device.isTorchModeSupported(torch)) { | ||
| 324 | return | 332 | return |
| 325 | } | 333 | } |
| 326 | 334 | ||
| @@ -337,7 +345,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | @@ -337,7 +345,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | ||
| 337 | } | 345 | } |
| 338 | } | 346 | } |
| 339 | 347 | ||
| 340 | - func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | 348 | + /// Reset the zoom scale. |
| 349 | + private func resetScale(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | ||
| 350 | + // The zoom scale is not yet supported on MacOS. | ||
| 351 | + result(nil) | ||
| 352 | + } | ||
| 353 | + | ||
| 354 | + /// Set the zoom scale. | ||
| 355 | + private func setScale(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | ||
| 356 | + // The zoom scale is not yet supported on MacOS. | ||
| 357 | + result(nil) | ||
| 358 | + } | ||
| 359 | + | ||
| 360 | + private func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | ||
| 341 | let requestedTorchMode: AVCaptureDevice.TorchMode = call.arguments as! Int == 1 ? .on : .off | 361 | let requestedTorchMode: AVCaptureDevice.TorchMode = call.arguments as! Int == 1 ? .on : .off |
| 342 | 362 | ||
| 343 | do { | 363 | do { |
-
Please register or login to post a comment