diff --git a/Sources/Control/Flashlight.swift b/Sources/Control/Flashlight.swift new file mode 100644 index 0000000..03001a0 --- /dev/null +++ b/Sources/Control/Flashlight.swift @@ -0,0 +1,75 @@ +// +// Flashlight.swift +// ControlKit +// + +import AVFoundation +import OSLog + +extension Control { + + /// 🔦 Control the device's flashlight. + public enum Flashlight {} +} + +extension Control.Flashlight { + + /// Indicates whether the device's flashlight is currently turned on. + /// + /// - Returns: A Boolean value indicating the flashlight state. Returns `true` if the flashlight is on, otherwise `false`. + public static var isOn: Bool { + (deviceWithFlashlight?.torchLevel ?? 0) > 0 + } + + /// Toggles the device's flashlight on/off. + /// + /// - Parameter isOn: A Boolean value to specify the desired state of the flashlight. + /// Pass `true` to turn it on or `false` to turn it off. + /// If no value is provided, the flashlight toggles its current state. + /// - Important: The flashlight can only be used while the app is in the foreground. + /// If the flashlight is on and the app is backgrounded, the flashlight will turn off. + /// - Note: If the device does not have a flashlight, this method does nothing. + public static func toggle( _ isOn: Bool = !isOn) { + guard let deviceWithFlashlight else { + return + } + do { + try deviceWithFlashlight.lockForConfiguration() + if isOn { + try deviceWithFlashlight.setTorchModeOn(level: AVCaptureDevice.maxAvailableTorchLevel) + } else { + deviceWithFlashlight.torchMode = .off + } + deviceWithFlashlight.unlockForConfiguration() + } catch { + log.error("Error toggling flashlight: \(error.localizedDescription) to \(isOn ? "on" : "off")") + } + } + + public static func blink(count: Int = 1, interval: TimeInterval = 0.1) { + Task { + for _ in 0..