Julian Steenbakker

Merge branch 'master' into ci

# Conflicts:
#	.github/workflows/flutter.yml
... ... @@ -7,7 +7,7 @@
release-please:
runs-on: ubuntu-latest
steps:
- uses: GoogleCloudPlatform/release-please-action@v3.7.13
- uses: GoogleCloudPlatform/release-please-action@v4.0.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
release-type: simple
... ...
... ... @@ -69,6 +69,43 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
super.init()
}
/// Get the default camera device for the given `position`.
///
/// This function selects the most appropriate camera, when it is available.
private func getDefaultCameraDevice(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
if #available(iOS 13.0, *) {
// Find the built-in Triple Camera, if it exists.
if let device = AVCaptureDevice.default(.builtInTripleCamera,
for: .video,
position: position) {
return device
}
// Find the built-in Dual-Wide Camera, if it exists.
if let device = AVCaptureDevice.default(.builtInDualWideCamera,
for: .video,
position: position) {
return device
}
}
// Find the built-in Dual Camera, if it exists.
if let device = AVCaptureDevice.default(.builtInDualCamera,
for: .video,
position: position) {
return device
}
// Find the built-in Wide-Angle Camera, if it exists.
if let device = AVCaptureDevice.default(.builtInWideAngleCamera,
for: .video,
position: position) {
return device
}
return nil
}
/// Check if we already have camera permission.
func checkPermission() -> Int {
let status = AVCaptureDevice.authorizationStatus(for: .video)
... ... @@ -146,11 +183,7 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
textureId = registry?.register(self)
// Open the camera device
if #available(iOS 13.0, *) {
device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInTripleCamera, .builtInDualWideCamera, .builtInDualCamera, .builtInWideAngleCamera], mediaType: .video, position: cameraPosition).devices.first
} else {
device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInWideAngleCamera], mediaType: .video, position: cameraPosition).devices.first
}
device = getDefaultCameraDevice(position: cameraPosition)
if (device == nil) {
throw MobileScannerError.noCamera
... ... @@ -215,26 +248,35 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
backgroundQueue.async {
self.captureSession.startRunning()
// Turn on the flashlight if requested,
// but after the capture session started.
// After the capture session started, turn on the torch (if requested)
// and reset the zoom scale back to the default.
// Ensure that these adjustments are done on the main DispatchQueue,
// as they interact with the hardware camera.
if (torch) {
DispatchQueue.main.async {
do {
try self.toggleTorch(.on)
} catch {
// If the torch does not turn on,
// continue with the capture session anyway.
}
}
}
DispatchQueue.main.async {
do {
try self.toggleTorch(.on)
try self.resetScale()
} catch {
// If the torch does not turn on,
// If the zoom scale could not be reset,
// continue with the capture session anyway.
}
}
do {
try self.resetScale()
} catch {
// If the zoom scale could not be reset,
// continue with the capture session anyway.
}
if let device = self.device {
// When querying the dimensions of the camera,
// stay on the background thread,
// as this does not change the configuration of the hardware camera.
let dimensions = CMVideoFormatDescriptionGetDimensions(
device.activeFormat.formatDescription)
let hasTorch = device.hasTorch
... ... @@ -277,12 +319,18 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
device = nil
}
/// Toggle the flashlight between on and off.
/// Set the torch mode.
///
/// This method should be called on the main DispatchQueue.
func toggleTorch(_ torch: AVCaptureDevice.TorchMode) throws {
if (device == nil || !device.hasTorch || !device.isTorchAvailable) {
guard let device = self.device else {
return
}
if (!device.hasTorch || !device.isTorchAvailable || !device.isTorchModeSupported(torch)) {
return
}
if (device.torchMode != torch) {
try device.lockForConfiguration()
device.torchMode = torch
... ...
... ... @@ -61,6 +61,10 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
start(call, result)
case "torch":
toggleTorch(call, result)
case "setScale":
setScale(call, result)
case "resetScale":
resetScale(call, result)
// case "analyze":
// switchAnalyzeMode(call, result)
case "stop":
... ... @@ -320,7 +324,11 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
// TODO: this method should be removed when iOS and MacOS share their implementation.
private func toggleTorchInternal(_ torch: AVCaptureDevice.TorchMode) throws {
if (device == nil || !device.hasTorch) {
guard let device = self.device else {
return
}
if (!device.hasTorch || !device.isTorchModeSupported(torch)) {
return
}
... ... @@ -337,7 +345,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
}
}
func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
/// Reset the zoom scale.
private func resetScale(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
// The zoom scale is not yet supported on MacOS.
result(nil)
}
/// Set the zoom scale.
private func setScale(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
// The zoom scale is not yet supported on MacOS.
result(nil)
}
private func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
let requestedTorchMode: AVCaptureDevice.TorchMode = call.arguments as! Int == 1 ? .on : .off
do {
... ...