| 
 | 1 | +//  | 
 | 2 | +// Flashlight.swift  | 
 | 3 | +// ControlKit  | 
 | 4 | +//  | 
 | 5 | + | 
 | 6 | +import AVFoundation  | 
 | 7 | +import OSLog  | 
 | 8 | + | 
 | 9 | +extension Control {  | 
 | 10 | + | 
 | 11 | + /// 🔦 Control the device's flashlight.  | 
 | 12 | + public enum Flashlight {}  | 
 | 13 | +}  | 
 | 14 | + | 
 | 15 | +extension Control.Flashlight {  | 
 | 16 | + | 
 | 17 | + /// Indicates whether the device's flashlight is currently turned on.  | 
 | 18 | + ///  | 
 | 19 | + /// - Returns: A Boolean value indicating the flashlight state. Returns `true` if the flashlight is on, otherwise `false`.  | 
 | 20 | + public static var isOn: Bool {  | 
 | 21 | + (deviceWithFlashlight?.torchLevel ?? 0) > 0  | 
 | 22 | + }  | 
 | 23 | + | 
 | 24 | + /// Toggles the state of the device's flashlight.  | 
 | 25 | + ///  | 
 | 26 | + /// - Parameter isOn: A Boolean value to specify the desired state of the flashlight.  | 
 | 27 | + /// Pass `true` to turn it on or `false` to turn it off.  | 
 | 28 | + /// If no value is provided, the flashlight toggles its current state.  | 
 | 29 | + /// - Important: The flashlight can only be used while the app is in the foreground.  | 
 | 30 | + /// If the flashlight is on and the app is backgrounded, the flashlight will turn off.  | 
 | 31 | + /// - Note: If the device does not have a flashlight, this method does nothing.  | 
 | 32 | + public static func toggleFlashlight( _ isOn: Bool = !isOn) {  | 
 | 33 | + guard let deviceWithFlashlight else {  | 
 | 34 | + return  | 
 | 35 | + }  | 
 | 36 | + do {  | 
 | 37 | + try deviceWithFlashlight.lockForConfiguration()  | 
 | 38 | + if isOn {  | 
 | 39 | + try deviceWithFlashlight.setTorchModeOn(level: AVCaptureDevice.maxAvailableTorchLevel)  | 
 | 40 | + } else {  | 
 | 41 | + deviceWithFlashlight.torchMode = .off  | 
 | 42 | + }  | 
 | 43 | + deviceWithFlashlight.unlockForConfiguration()  | 
 | 44 | + } catch {  | 
 | 45 | + log.error("Error toggling flashlight: \(error.localizedDescription) to \(isOn ? "on" : "off")")  | 
 | 46 | + }  | 
 | 47 | + }  | 
 | 48 | + | 
 | 49 | + private static var deviceWithFlashlight: AVCaptureDevice? {  | 
 | 50 | + guard  | 
 | 51 | + let device = AVCaptureDevice.default(for: .video),  | 
 | 52 | + device.hasTorch  | 
 | 53 | + else {  | 
 | 54 | + #if targetEnvironment(simulator)  | 
 | 55 | + log.info("Simulator does not have a flashlight (yet)")  | 
 | 56 | + #else  | 
 | 57 | + log.info("Flashlight (torch) not available")  | 
 | 58 | + #endif  | 
 | 59 | + return nil  | 
 | 60 | + }  | 
 | 61 | + return device  | 
 | 62 | + }  | 
 | 63 | + | 
 | 64 | + private static let log = Logger(subsystem: Control.subsystem, category: "Flashlight")  | 
 | 65 | +}  | 
0 commit comments