             _continuousIndicator.isHidden = true
         }
         
-        private func _setupFocusTapGesture() {
+        private func _setupFocusGestures() {
             let tap = UITapGestureRecognizer(target: self, action: #selector(_handleTapToConfigureDevice(_:)))
             addGestureRecognizer(tap)
             _focusTapGesture = tap
+            
+            let longPress = UILongPressGestureRecognizer(target: self, action: #selector(_handleLongPressToConfigureDevice(_:)))
+            addGestureRecognizer(longPress)
+            _focusLongPressGesture = longPress
         }
         
         private func _observeProperties() {
             if let device = videoDevice {
                 device.addObserver(self, forKeyPath: "adjustingFocus", options: .new, context: &_deviceIsAdjustingFocusObserveContext)
                 device.addObserver(self, forKeyPath: "focusMode", options: .new, context: &_deviceFocusModeObserveContext)
+                device.addObserver(self, forKeyPath: "flashActive", options: .new, context: &_deviceFlashActiveObserveContext)
             }
         }
         private func _observeNotifications() {
             NotificationCenter.default.addObserver(self, selector: #selector(_handleCaptureDeviceSubjectAreaDidChange(_:)), name: .AVCaptureDeviceSubjectAreaDidChange, object: nil)
+        }
+        
+        private func _setupHumanReadingInfos() {
+            for arrangedView in _infoStackView.arrangedSubviews {
+                _infoStackView.removeArrangedSubview(arrangedView)
+                arrangedView.removeFromSuperview()
+            }
+            
+            guard !humanReadingInfos.isEmpty else { return }
+            
+            for info in humanReadingInfos {
+                let infoView = UIView()
+                infoView.translatesAutoresizingMaskIntoConstraints = false
+                infoView.backgroundColor = UIColor(colorLiteralRed: 1.0, green: 0.8, blue: 0.0, alpha: 1.0)
+                infoView.layer.cornerRadius = 2.0
+                infoView.layer.masksToBounds = true
+                
+                switch info {
+                case let image as UIImage:
+                    let imageView = _ImageView(image: image)
+                    imageView.contentMode = .scaleAspectFit
+                    imageView.translatesAutoresizingMaskIntoConstraints = false
+                    infoView.addSubview(imageView)
+                    imageView.centerXAnchor.constraint(equalTo: infoView.centerXAnchor).isActive = true
+                    imageView.centerYAnchor.constraint(equalTo: infoView.centerYAnchor).isActive = true
+                    imageView.topAnchor.constraint(equalTo: infoView.topAnchor, constant: 2.0).isActive = true
+                    imageView.bottomAnchor.constraint(equalTo: infoView.bottomAnchor, constant: -2.0).isActive = true
+                    imageView.leadingAnchor.constraint(equalTo: infoView.leadingAnchor, constant: 8.0).isActive = true
+                    imageView.trailingAnchor.constraint(equalTo: infoView.trailingAnchor, constant: -8.0).isActive = true
+                case let content as String:
+                    let label = UILabel()
+                    label.translatesAutoresizingMaskIntoConstraints = false
+                    label.font = UIFont.systemFont(ofSize: 14)
+                    label.textColor = UIColor.black.withAlphaComponent(0.88)
+                    label.text = content
+                    infoView.addSubview(label)
+                    label.topAnchor.constraint(equalTo: infoView.topAnchor, constant: 2.0).isActive = true
+                    label.bottomAnchor.constraint(equalTo: infoView.bottomAnchor, constant: -2.0).isActive = true
+                    label.leadingAnchor.constraint(equalTo: infoView.leadingAnchor, constant: 8.0).isActive = true
+                    label.trailingAnchor.constraint(equalTo: infoView.trailingAnchor, constant: -8.0).isActive = true
+                default: return
+                }
+                
+                _infoStackView.addArrangedSubview(infoView)
+            }
+            
+            _infoStackView.alpha = 0.0
+            UIView.animate(withDuration: 0.25) { [unowned self] in
+                self._infoStackView.alpha = 1.0
+            }
         }
     }
 }

        }
    }
    
    private func _animateContinuousIndicator(_ show: Bool, at point: CGPoint) {
        if show {
            guard _continuousIndicator.isHidden else { return }
            
            _continuousBeginning = Date()
            _continuousIndicator.isHidden = false
            _continuousIndicator.center = point
            _continuousIndicator.alpha = 0.0
            
            let scale: CGFloat = 1.2
            _continuousIndicator.transform = CGAffineTransform(scaleX: scale, y: scale)
            UIView.animate(withDuration: 0.1, animations: { [unowned self] in
                self._continuousIndicator.alpha = 1.0
            }, completion: { (finished) in
                if finished {
                    UIView.animate(withDuration: 0.25, animations: { [unowned self] in
                        self._continuousIndicator.transform = .identity
                    }, completion: { [unowned self] (finished) in
                        if finished {
                            self._twinkle(content: self._continuousIndicator)
                        }
                    })
                }
            })
        } else {
            guard !_continuousIndicator.isHidden else { return }
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + max(0.0, _graceTime - Date().timeIntervalSince(_continuousBeginning)), execute: { [unowned self] in
                self._untwinkle(content: self._continuousIndicator)
                UIView.animate(withDuration: 0.25, delay: 0.4, options: [], animations: { [unowned self] in
                    self._continuousIndicator.alpha = 0.0
                }, completion: { [unowned self] finished in
                    if finished {
                        self._continuousIndicator.isHidden = true
                    }
                })
            })
        }
    }
    
    private func _animateAutoIndicators(_ show: Bool, at point: CGPoint) {
        if show {
            _autoBeginning = Date()
            _autoFocusIndicator.isHidden = false
            _autoExposeIndicator.isHidden = false
            _autoFocusIndicator.alpha = 0.0
            _autoExposeIndicator.alpha = 0.0
            _autoFocusIndicator.center = point
            
            let scale: CGFloat = 1.5
            _autoFocusIndicator.transform = CGAffineTransform(scaleX: scale, y: scale)
            switch point.x {
            case 0...(bounds.width - _autoFocusIndicator.bounds.width * 0.5 - (_paddingOfFocusAndExpose + _autoExposeIndicator.bounds.width)):

        
        var _autoBeginning: Date = Date()
        var _continuousBeginning: Date = Date()
        let _graceTime: Double = 0.35
        let _paddingOfFocusAndExpose: CGFloat = 5.0
        
        var _deviceIsAdjustingFocusObserveContext = 0
        var _deviceFocusModeObserveContext = 1
        var _deviceFlashActiveObserveContext = 2
        
        init(session: AVCaptureSession) {
            super.init(frame: .zero)
