Commit 22717582 by Daniel Dahan

updated comments to CaptureSession

parent 17b67d99
...@@ -53,9 +53,13 @@ public class CapturePreview : MaterialView { ...@@ -53,9 +53,13 @@ public class CapturePreview : MaterialView {
return (layer as! AVCaptureVideoPreviewLayer).pointForCaptureDevicePoint(ofInterest: point) return (layer as! AVCaptureVideoPreviewLayer).pointForCaptureDevicePoint(ofInterest: point)
} }
/** /**
:name: prepareView Prepares the view instance when intialized. When subclassing,
*/ it is recommended to override the prepareView method
to initialize property values and other setup operations.
The super.prepareView method should always be called immediately
when subclassing.
*/
public override func prepareView() { public override func prepareView() {
super.prepareView() super.prepareView()
preparePreviewLayer() preparePreviewLayer()
......
...@@ -34,52 +34,53 @@ import AVFoundation ...@@ -34,52 +34,53 @@ import AVFoundation
private var CaptureSessionAdjustingExposureContext: UInt8 = 1 private var CaptureSessionAdjustingExposureContext: UInt8 = 1
public enum CaptureSessionPreset { public enum CaptureSessionPreset {
case PresetPhoto case presetPhoto
case PresetHigh case presetHigh
case PresetMedium case presetMedium
case PresetLow case presetLow
case Preset352x288 case preset352x288
case Preset640x480 case preset640x480
case Preset1280x720 case preset1280x720
case Preset1920x1080 case preset1920x1080
case Preset3840x2160 case preset3840x2160
case PresetiFrame960x540 case presetiFrame960x540
case PresetiFrame1280x720 case presetiFrame1280x720
case PresetInputPriority case presetInputPriority
} }
/** /**
:name: CaptureSessionPresetToString Converts a given CaptureSessionPreset to a String value.
*/ - Parameter preset: A CaptureSessionPreset to convert.
*/
public func CaptureSessionPresetToString(preset: CaptureSessionPreset) -> String { public func CaptureSessionPresetToString(preset: CaptureSessionPreset) -> String {
switch preset { switch preset {
case .PresetPhoto: case .presetPhoto:
return AVCaptureSessionPresetPhoto return AVCaptureSessionPresetPhoto
case .PresetHigh: case .presetHigh:
return AVCaptureSessionPresetHigh return AVCaptureSessionPresetHigh
case .PresetMedium: case .presetMedium:
return AVCaptureSessionPresetMedium return AVCaptureSessionPresetMedium
case .PresetLow: case .presetLow:
return AVCaptureSessionPresetLow return AVCaptureSessionPresetLow
case .Preset352x288: case .preset352x288:
return AVCaptureSessionPreset352x288 return AVCaptureSessionPreset352x288
case .Preset640x480: case .preset640x480:
return AVCaptureSessionPreset640x480 return AVCaptureSessionPreset640x480
case .Preset1280x720: case .preset1280x720:
return AVCaptureSessionPreset1280x720 return AVCaptureSessionPreset1280x720
case .Preset1920x1080: case .preset1920x1080:
return AVCaptureSessionPreset1920x1080 return AVCaptureSessionPreset1920x1080
case .Preset3840x2160: case .preset3840x2160:
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
return AVCaptureSessionPreset3840x2160 return AVCaptureSessionPreset3840x2160
} else { } else {
return AVCaptureSessionPresetHigh return AVCaptureSessionPresetHigh
} }
case .PresetiFrame960x540: case .presetiFrame960x540:
return AVCaptureSessionPresetiFrame960x540 return AVCaptureSessionPresetiFrame960x540
case .PresetiFrame1280x720: case .presetiFrame1280x720:
return AVCaptureSessionPresetiFrame1280x720 return AVCaptureSessionPresetiFrame1280x720
case .PresetInputPriority: case .presetInputPriority:
return AVCaptureSessionPresetInputPriority return AVCaptureSessionPresetInputPriority
} }
} }
...@@ -116,7 +117,7 @@ public protocol CaptureSessionDelegate { ...@@ -116,7 +117,7 @@ public protocol CaptureSessionDelegate {
- Parameter image: An image that has been captured. - Parameter image: An image that has been captured.
*/ */
@objc @objc
optional func captureStillImageAsynchronously(captureSession: CaptureSession, image: UIImage) optional func captureSessionStillImageAsynchronously(captureSession: CaptureSession, image: UIImage)
/** /**
A delegation method that is fired when capturing an image asynchronously has failed. A delegation method that is fired when capturing an image asynchronously has failed.
...@@ -124,161 +125,136 @@ public protocol CaptureSessionDelegate { ...@@ -124,161 +125,136 @@ public protocol CaptureSessionDelegate {
- Parameter error: A NSError corresponding to the error. - Parameter error: A NSError corresponding to the error.
*/ */
@objc @objc
optional func captureStillImageAsynchronouslyFailedWithError(captureSession: CaptureSession, error: NSError) optional func captureSessionStillImageAsynchronouslyFailedWithError(captureSession: CaptureSession, error: NSError)
/** /**
:name: captureCreateMovieFileFailedWithError A delegation method that is fired when creating a movie file has failed.
*/ - Parameter captureSession: A reference to the calling CaptureSession.
- Parameter error: A NSError corresponding to the error.
*/
@objc @objc
optional func captureCreateMovieFileFailedWithError(captureSession: CaptureSession, error: NSError) optional func captureSessionCreateMovieFileFailedWithError(captureSession: CaptureSession, error: NSError)
/** /**
:name: captureMovieFailedWithError A delegation method that is fired when capturing a movie has failed.
*/ - Parameter captureSession: A reference to the calling CaptureSession.
- Parameter error: A NSError corresponding to the error.
*/
@objc @objc
optional func captureMovieFailedWithError(captureSession: CaptureSession, error: NSError) optional func captureSessionMovieFailedWithError(captureSession: CaptureSession, error: NSError)
/** /**
:name: captureDidStartRecordingToOutputFileAtURL A delegation method that is fired when a session started recording and writing
*/ to a file.
- Parameter captureSession: A reference to the calling CaptureSession.
- Parameter captureOut: An AVCaptureFileOutput.
- Parameter fileURL: A file URL.
- Parameter fromConnections: An array of AnyObjects.
*/
@objc @objc
optional func captureDidStartRecordingToOutputFileAtURL(captureSession: CaptureSession, captureOutput: AVCaptureFileOutput, fileURL: NSURL, fromConnections connections: [AnyObject]) optional func captureSessionDidStartRecordingToOutputFileAtURL(captureSession: CaptureSession, captureOutput: AVCaptureFileOutput, fileURL: NSURL, fromConnections connections: [AnyObject])
/** /**
:name: captureDidFinishRecordingToOutputFileAtURL A delegation method that is fired when a session finished recording and writing
*/ to a file.
- Parameter captureSession: A reference to the calling CaptureSession.
- Parameter captureOut: An AVCaptureFileOutput.
- Parameter fileURL: A file URL.
- Parameter fromConnections: An array of AnyObjects.
- Parameter error: A NSError corresponding to an error.
*/
@objc @objc
optional func captureDidFinishRecordingToOutputFileAtURL(captureSession: CaptureSession, captureOutput: AVCaptureFileOutput, outputFileURL: NSURL, fromConnections connections: [AnyObject], error: NSError!) optional func captureSessionDidFinishRecordingToOutputFileAtURL(captureSession: CaptureSession, captureOutput: AVCaptureFileOutput, outputFileURL: NSURL, fromConnections connections: [AnyObject], error: NSError!)
} }
@objc(CaptureSession) @objc(CaptureSession)
public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
/** /// A reference to the session DispatchQueue.
:name: sessionQueue
*/
private var sessionQueue: DispatchQueue! private var sessionQueue: DispatchQueue!
/** /// A reference to the active video input.
:name: activeVideoInput
*/
private var activeVideoInput: AVCaptureDeviceInput? private var activeVideoInput: AVCaptureDeviceInput?
/** /// A reference to the active audio input.
:name: activeAudioInput
*/
private var activeAudioInput: AVCaptureDeviceInput? private var activeAudioInput: AVCaptureDeviceInput?
/** /// A reference to the image output.
:name: imageOutput private var imageOutput: AVCaptureStillImageOutput!
*/
private lazy var imageOutput: AVCaptureStillImageOutput = AVCaptureStillImageOutput()
/** /// A reference to the movie output.
:name: movieOutput private var movieOutput: AVCaptureMovieFileOutput!
*/
private lazy var movieOutput: AVCaptureMovieFileOutput = AVCaptureMovieFileOutput()
/** /// A reference to the movie output URL.
:name: movieOutputURL
*/
private var movieOutputURL: NSURL? private var movieOutputURL: NSURL?
/** /// A reference to the AVCaptureSession.
:name: session internal var session: AVCaptureSession!
*/
internal lazy var session: AVCaptureSession = AVCaptureSession()
/** /// A boolean indicating if the session is running.
:name: isRunning public private(set) var isRunning: Bool = false
*/
public private(set) lazy var isRunning: Bool = false
/** /// A boolean indicating if the session is recording.
:name: isRecording public private(set) var isRecording: Bool = false
*/
public private(set) lazy var isRecording: Bool = false
/** /// A reference to the recorded time duration.
:name: recordedDuration public var recordedDuration: CMTime {
*/
public var recordedDuration: CMTime {
return movieOutput.recordedDuration return movieOutput.recordedDuration
} }
/** /// An optional reference to the active camera if one exists.
:name: activeCamera
*/
public var activeCamera: AVCaptureDevice? { public var activeCamera: AVCaptureDevice? {
return activeVideoInput?.device return activeVideoInput?.device
} }
/** /// An optional reference to the inactive camera if one exists.
:name: inactiveCamera
*/
public var inactiveCamera: AVCaptureDevice? { public var inactiveCamera: AVCaptureDevice? {
var device: AVCaptureDevice? var device: AVCaptureDevice?
if 1 < cameraCount { if 1 < cameraCount {
if activeCamera?.position == .back { if activeCamera?.position == .back {
device = cameraWithPosition(position: .front) device = camera(position: .front)
} else { } else {
device = cameraWithPosition(position: .back) device = camera(position: .back)
} }
} }
return device return device
} }
/** /// Available number of cameras.
:name: cameraCount
*/
public var cameraCount: Int { public var cameraCount: Int {
return AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo).count return AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo).count
} }
/** /// A boolean indicating whether the camera can switch to another.
:name: canSwitchCameras
*/
public var canSwitchCameras: Bool { public var canSwitchCameras: Bool {
return 1 < cameraCount return 1 < cameraCount
} }
/** /// A booealn indicating whether the camrea supports focus.
:name: caneraSupportsTapToFocus public var isFocusPointOfInterestSupported: Bool {
*/
public var cameraSupportsTapToFocus: Bool {
return nil == activeCamera ? false : activeCamera!.isFocusPointOfInterestSupported return nil == activeCamera ? false : activeCamera!.isFocusPointOfInterestSupported
} }
/** /// A booealn indicating whether the camrea supports exposure.
:name: cameraSupportsTapToExpose public var isExposurePointOfInterestSupported: Bool {
*/
public var cameraSupportsTapToExpose: Bool {
return nil == activeCamera ? false : activeCamera!.isExposurePointOfInterestSupported return nil == activeCamera ? false : activeCamera!.isExposurePointOfInterestSupported
} }
/** /// A boolean indicating if the active camera has flash.
:name: cameraHasFlash public var hasFlash: Bool {
*/
public var cameraHasFlash: Bool {
return nil == activeCamera ? false : activeCamera!.hasFlash return nil == activeCamera ? false : activeCamera!.hasFlash
} }
/** /// A boolean indicating if the active camera has a torch.
:name: cameraHasTorch public var hasTorch: Bool {
*/
public var cameraHasTorch: Bool {
return nil == activeCamera ? false : activeCamera!.hasTorch return nil == activeCamera ? false : activeCamera!.hasTorch
} }
/** /// A reference to the active camera position if the active camera exists.
:name: cameraPosition public var position: AVCaptureDevicePosition? {
*/
public var cameraPosition: AVCaptureDevicePosition? {
return activeCamera?.position return activeCamera?.position
} }
/** /// A reference to the focusMode.
:name: focusMode
*/
public var focusMode: AVCaptureFocusMode { public var focusMode: AVCaptureFocusMode {
get { get {
return activeCamera!.focusMode return activeCamera!.focusMode
...@@ -302,14 +278,12 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -302,14 +278,12 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
userInfo[NSUnderlyingErrorKey] = error userInfo[NSUnderlyingErrorKey] = error
} }
if let e: NSError = error { if let e: NSError = error {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
} }
/** /// A reference to the flashMode.
:name: flashMode
*/
public var flashMode: AVCaptureFlashMode { public var flashMode: AVCaptureFlashMode {
get { get {
return activeCamera!.flashMode return activeCamera!.flashMode
...@@ -333,14 +307,12 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -333,14 +307,12 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
userInfo[NSUnderlyingErrorKey] = error userInfo[NSUnderlyingErrorKey] = error
} }
if let e: NSError = error { if let e: NSError = error {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
} }
/** /// A reference to the torchMode.
:name: torchMode
*/
public var torchMode: AVCaptureTorchMode { public var torchMode: AVCaptureTorchMode {
get { get {
return activeCamera!.torchMode return activeCamera!.torchMode
...@@ -364,15 +336,15 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -364,15 +336,15 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
userInfo[NSUnderlyingErrorKey] = error userInfo[NSUnderlyingErrorKey] = error
} }
if let e: NSError = error { if let e: NSError = error {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
} }
/// The session quality preset. /// The session quality preset.
public var sessionPreset: CaptureSessionPreset { public var preset: CaptureSessionPreset {
didSet { didSet {
session.sessionPreset = CaptureSessionPresetToString(preset: sessionPreset) session.sessionPreset = CaptureSessionPresetToString(preset: preset)
} }
} }
...@@ -397,9 +369,13 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -397,9 +369,13 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
/// Initializer. /// Initializer.
public override init() { public override init() {
sessionPreset = .PresetHigh preset = .presetHigh
super.init() super.init()
prepareSession() prepareSession()
prepareActiveVideoInput()
prepareActiveAudioInput()
prepareImageOutput()
prepareMovieOutput()
} }
/// Starts the session. /// Starts the session.
...@@ -424,8 +400,8 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -424,8 +400,8 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
public func switchCameras() { public func switchCameras() {
if canSwitchCameras { if canSwitchCameras {
do { do {
if let v: AVCaptureDevicePosition = cameraPosition { if let v: AVCaptureDevicePosition = position {
delegate?.captureSessionWillSwitchCameras?(capture: self, position: v) delegate?.captureSessionWillSwitchCameras?(captureSession: self, position: v)
let videoInput: AVCaptureDeviceInput? = try AVCaptureDeviceInput(device: inactiveCamera!) let videoInput: AVCaptureDeviceInput? = try AVCaptureDeviceInput(device: inactiveCamera!)
session.beginConfiguration() session.beginConfiguration()
session.removeInput(activeVideoInput) session.removeInput(activeVideoInput)
...@@ -437,48 +413,57 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -437,48 +413,57 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
session.addInput(activeVideoInput) session.addInput(activeVideoInput)
} }
session.commitConfiguration() session.commitConfiguration()
delegate?.captureSessionDidSwitchCameras?(capture: self, position: cameraPosition!) delegate?.captureSessionDidSwitchCameras?(captureSession: self, position: position!)
} }
} catch let e as NSError { } catch let e as NSError {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
} }
/** /**
:name: isFocusModeSupported Checks if a given focus mode is supported.
*/ - Parameter focusMode: An AVCaptureFocusMode.
- Returns: A boolean of the result, true if supported, false otherwise.
*/
public func isFocusModeSupported(focusMode: AVCaptureFocusMode) -> Bool { public func isFocusModeSupported(focusMode: AVCaptureFocusMode) -> Bool {
return activeCamera!.isFocusModeSupported(focusMode) return activeCamera!.isFocusModeSupported(focusMode)
} }
/** /**
:name: isExposureModeSupported Checks if a given exposure mode is supported.
*/ - Parameter exposureMode: An AVCaptureExposureMode.
public func isExposureModeSupported(exposureMode: AVCaptureExposureMode) -> Bool { - Returns: A boolean of the result, true if supported, false otherwise.
*/
public func isExposureModeSupported(exposureMode: AVCaptureExposureMode) -> Bool {
return activeCamera!.isExposureModeSupported(exposureMode) return activeCamera!.isExposureModeSupported(exposureMode)
} }
/** /**
:name: isFlashModeSupported Checks if a given flash mode is supported.
*/ - Parameter flashMode: An AVCaptureFlashMode.
public func isFlashModeSupported(flashMode: AVCaptureFlashMode) -> Bool { - Returns: A boolean of the result, true if supported, false otherwise.
*/
public func isFlashModeSupported(flashMode: AVCaptureFlashMode) -> Bool {
return activeCamera!.isFlashModeSupported(flashMode) return activeCamera!.isFlashModeSupported(flashMode)
} }
/** /**
:name: isTorchModeSupported Checks if a given torch mode is supported.
*/ - Parameter torchMode: An AVCaptureTorchMode.
public func isTorchModeSupported(torchMode: AVCaptureTorchMode) -> Bool { - Returns: A boolean of the result, true if supported, false otherwise.
*/
public func isTorchModeSupported(torchMode: AVCaptureTorchMode) -> Bool {
return activeCamera!.isTorchModeSupported(torchMode) return activeCamera!.isTorchModeSupported(torchMode)
} }
/** /**
:name: focusAtPoint Focuses the camera at a given point.
*/ - Parameter at: A CGPoint to focus at.
public func focusAtPoint(point: CGPoint) { */
public func focus(at point: CGPoint) {
var error: NSError? var error: NSError?
if cameraSupportsTapToFocus && isFocusModeSupported(focusMode: .autoFocus) { if isFocusPointOfInterestSupported && isFocusModeSupported(focusMode: .autoFocus) {
do { do {
let device: AVCaptureDevice = activeCamera! let device: AVCaptureDevice = activeCamera!
try device.lockForConfiguration() try device.lockForConfiguration()
...@@ -490,22 +475,23 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -490,22 +475,23 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} else { } else {
var userInfo: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>() var userInfo: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
userInfo[NSLocalizedDescriptionKey] = "[Material Error: Unsupported focusAtPoint.]" userInfo[NSLocalizedDescriptionKey] = "[Material Error: Unsupported focus.]"
userInfo[NSLocalizedFailureReasonErrorKey] = "[Material Error: Unsupported focusAtPoint.]" userInfo[NSLocalizedFailureReasonErrorKey] = "[Material Error: Unsupported focus.]"
error = NSError(domain: "io.cosmicmind.Material.CaptureView", code: 0004, userInfo: userInfo) error = NSError(domain: "io.cosmicmind.Material.CaptureView", code: 0004, userInfo: userInfo)
userInfo[NSUnderlyingErrorKey] = error userInfo[NSUnderlyingErrorKey] = error
} }
if let e: NSError = error { if let e: NSError = error {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
/** /**
:name: exposeAtPoint Exposes the camera at a given point.
*/ - Parameter at: A CGPoint to expose at.
public func exposeAtPoint(point: CGPoint) { */
public func expose(at point: CGPoint) {
var error: NSError? var error: NSError?
if cameraSupportsTapToExpose && isExposureModeSupported(exposureMode: .continuousAutoExposure) { if isExposurePointOfInterestSupported && isExposureModeSupported(exposureMode: .continuousAutoExposure) {
do { do {
let device: AVCaptureDevice = activeCamera! let device: AVCaptureDevice = activeCamera!
try device.lockForConfiguration() try device.lockForConfiguration()
...@@ -520,19 +506,16 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -520,19 +506,16 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} else { } else {
var userInfo: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>() var userInfo: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
userInfo[NSLocalizedDescriptionKey] = "[Material Error: Unsupported exposeAtPoint.]" userInfo[NSLocalizedDescriptionKey] = "[Material Error: Unsupported expose.]"
userInfo[NSLocalizedFailureReasonErrorKey] = "[Material Error: Unsupported exposeAtPoint.]" userInfo[NSLocalizedFailureReasonErrorKey] = "[Material Error: Unsupported expose.]"
error = NSError(domain: "io.cosmicmind.Material.CaptureView", code: 0005, userInfo: userInfo) error = NSError(domain: "io.cosmicmind.Material.CaptureView", code: 0005, userInfo: userInfo)
userInfo[NSUnderlyingErrorKey] = error userInfo[NSUnderlyingErrorKey] = error
} }
if let e: NSError = error { if let e: NSError = error {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
/**
:name: observeValueForKeyPath
*/
public override func observeValue(forKeyPath keyPath: String?, of object: AnyObject?, change: [NSKeyValueChangeKey: AnyObject]?, context: UnsafeMutablePointer<Void>?) { public override func observeValue(forKeyPath keyPath: String?, of object: AnyObject?, change: [NSKeyValueChangeKey: AnyObject]?, context: UnsafeMutablePointer<Void>?) {
if context == &CaptureSessionAdjustingExposureContext { if context == &CaptureSessionAdjustingExposureContext {
let device: AVCaptureDevice = object as! AVCaptureDevice let device: AVCaptureDevice = object as! AVCaptureDevice
...@@ -544,7 +527,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -544,7 +527,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
device.exposureMode = .locked device.exposureMode = .locked
device.unlockForConfiguration() device.unlockForConfiguration()
} catch let e as NSError { } catch let e as NSError {
self.delegate?.captureSessionFailedWithError?(capture: self, error: e) self.delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
} }
...@@ -554,32 +537,32 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -554,32 +537,32 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
/** /**
:name: resetFocusAndExposureModes Resets the camera focus and exposure.
*/ - Parameter focus: A boolean indicating to reset the focus.
public func resetFocusAndExposureModes() { - Parameter exposure: A boolean indicating to reset the exposure.
*/
public func reset(focus: Bool = true, exposure: Bool = true) {
let device: AVCaptureDevice = activeCamera! let device: AVCaptureDevice = activeCamera!
let canResetFocus: Bool = device.isFocusPointOfInterestSupported && device.isFocusModeSupported(.continuousAutoFocus) let canResetFocus: Bool = device.isFocusPointOfInterestSupported && device.isFocusModeSupported(.continuousAutoFocus)
let canResetExposure: Bool = device.isExposurePointOfInterestSupported && device.isExposureModeSupported(.continuousAutoExposure) let canResetExposure: Bool = device.isExposurePointOfInterestSupported && device.isExposureModeSupported(.continuousAutoExposure)
let centerPoint: CGPoint = CGPoint(x: 0.5, y: 0.5) let centerPoint: CGPoint = CGPoint(x: 0.5, y: 0.5)
do { do {
try device.lockForConfiguration() try device.lockForConfiguration()
if canResetFocus { if canResetFocus && focus {
device.focusMode = .continuousAutoFocus device.focusMode = .continuousAutoFocus
device.focusPointOfInterest = centerPoint device.focusPointOfInterest = centerPoint
} }
if canResetExposure { if canResetExposure && exposure {
device.exposureMode = .continuousAutoExposure device.exposureMode = .continuousAutoExposure
device.exposurePointOfInterest = centerPoint device.exposurePointOfInterest = centerPoint
} }
device.unlockForConfiguration() device.unlockForConfiguration()
} catch let e as NSError { } catch let e as NSError {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
/** /// Captures a still image.
:name: captureStillImage
*/
public func captureStillImage() { public func captureStillImage() {
sessionQueue.async() { [weak self] in sessionQueue.async() { [weak self] in
if let s: CaptureSession = self { if let s: CaptureSession = self {
...@@ -592,7 +575,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -592,7 +575,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
let data: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer) let data: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
if let image1: UIImage = UIImage(data: data as Data) { if let image1: UIImage = UIImage(data: data as Data) {
if let image2: UIImage = s.adjustOrientationForImage(image: image1) { if let image2: UIImage = s.adjustOrientationForImage(image: image1) {
s.delegate?.captureStillImageAsynchronously?(capture: s, image: image2) s.delegate?.captureSessionStillImageAsynchronously?(captureSession: s, image: image2)
} else { } else {
var userInfo: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>() var userInfo: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
userInfo[NSLocalizedDescriptionKey] = "[Material Error: Cannot fix image orientation.]" userInfo[NSLocalizedDescriptionKey] = "[Material Error: Cannot fix image orientation.]"
...@@ -610,7 +593,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -610,7 +593,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
if let e: NSError = captureError { if let e: NSError = captureError {
s.delegate?.captureStillImageAsynchronouslyFailedWithError?(capture: s, error: e) s.delegate?.captureSessionStillImageAsynchronouslyFailedWithError?(captureSession: s, error: e)
} }
} }
} }
...@@ -619,9 +602,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -619,9 +602,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} }
/** /// Starts recording.
:name: startRecording
*/
public func startRecording() { public func startRecording() {
if !isRecording { if !isRecording {
sessionQueue.async() { [weak self] in sessionQueue.async() { [weak self] in
...@@ -637,7 +618,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -637,7 +618,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
v.isSmoothAutoFocusEnabled = true v.isSmoothAutoFocusEnabled = true
v.unlockForConfiguration() v.unlockForConfiguration()
} catch let e as NSError { } catch let e as NSError {
s.delegate?.captureSessionFailedWithError?(capture: s, error: e) s.delegate?.captureSessionFailedWithError?(captureSession: s, error: e)
} }
} }
...@@ -651,29 +632,21 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -651,29 +632,21 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} }
/** /// Stops recording.
:name: stopRecording
*/
public func stopRecording() { public func stopRecording() {
if isRecording { if isRecording {
movieOutput.stopRecording() movieOutput.stopRecording()
} }
} }
/** public func capture(_ captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAt fileURL: URL!, fromConnections connections: [AnyObject]!) {
:name: captureOutput
*/
public func capture(_ captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAt fileURL: URL!, fromConnections connections: [AnyObject]!) {
isRecording = true isRecording = true
delegate?.captureDidStartRecordingToOutputFileAtURL?(capture: self, captureOutput: captureOutput, fileURL: fileURL, fromConnections: connections) delegate?.captureSessionDidStartRecordingToOutputFileAtURL?(captureSession: self, captureOutput: captureOutput, fileURL: fileURL, fromConnections: connections)
} }
/** public func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [AnyObject]!, error: NSError!) {
:name: captureOutput
*/
public func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [AnyObject]!, error: NSError!) {
isRecording = false isRecording = false
delegate?.captureDidFinishRecordingToOutputFileAtURL?(capture: self, captureOutput: captureOutput, outputFileURL: outputFileURL, fromConnections: connections, error: error) delegate?.captureSessionDidFinishRecordingToOutputFileAtURL?(captureSession: self, captureOutput: captureOutput, outputFileURL: outputFileURL, fromConnections: connections, error: error)
} }
/// Prepares the sessionQueue. /// Prepares the sessionQueue.
...@@ -681,67 +654,58 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -681,67 +654,58 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
sessionQueue = DispatchQueue(label: "io.cosmicmind.Material.CaptureSession", attributes: .serial, target: nil) sessionQueue = DispatchQueue(label: "io.cosmicmind.Material.CaptureSession", attributes: .serial, target: nil)
} }
/** /// Prepares the session.
:name: prepareSession
*/
private func prepareSession() { private func prepareSession() {
prepareVideoInput() session = AVCaptureSession()
prepareAudioInput()
prepareImageOutput()
prepareMovieOutput()
} }
/** /// Prepares the activeVideoInput.
:name: prepareVideoInput private func prepareActiveVideoInput() {
*/
private func prepareVideoInput() {
do { do {
activeVideoInput = try AVCaptureDeviceInput(device: AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)) activeVideoInput = try AVCaptureDeviceInput(device: AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo))
if session.canAddInput(activeVideoInput) { if session.canAddInput(activeVideoInput) {
session.addInput(activeVideoInput) session.addInput(activeVideoInput)
} }
} catch let e as NSError { } catch let e as NSError {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
/** /// Prepares the activeAudioInput.
:name: prepareAudioInput private func prepareActiveAudioInput() {
*/
private func prepareAudioInput() {
do { do {
activeAudioInput = try AVCaptureDeviceInput(device: AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio)) activeAudioInput = try AVCaptureDeviceInput(device: AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio))
if session.canAddInput(activeAudioInput) { if session.canAddInput(activeAudioInput) {
session.addInput(activeAudioInput) session.addInput(activeAudioInput)
} }
} catch let e as NSError { } catch let e as NSError {
delegate?.captureSessionFailedWithError?(capture: self, error: e) delegate?.captureSessionFailedWithError?(captureSession: self, error: e)
} }
} }
/** /// Prepares the imageOutput.
:name: prepareImageOutput
*/
private func prepareImageOutput() { private func prepareImageOutput() {
if session.canAddOutput(imageOutput) { if session.canAddOutput(imageOutput) {
imageOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG] imageOutput = AVCaptureStillImageOutput()
imageOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
session.addOutput(imageOutput) session.addOutput(imageOutput)
} }
} }
/** /// Prepares the movieOutput.
:name: prepareMovieOutput
*/
private func prepareMovieOutput() { private func prepareMovieOutput() {
if session.canAddOutput(movieOutput) { if session.canAddOutput(movieOutput) {
movieOutput = AVCaptureMovieFileOutput()
session.addOutput(movieOutput) session.addOutput(movieOutput)
} }
} }
/** /**
:name: cameraWithPosition A reference to the camera at a given position, if one exists.
*/ - Parameter at: An AVCaptureDevicePosition.
private func cameraWithPosition(position: AVCaptureDevicePosition) -> AVCaptureDevice? { - Returns: An AVCaptureDevice if one exists, or nil otherwise.
*/
private func camera(at position: AVCaptureDevicePosition) -> AVCaptureDevice? {
let devices: Array<AVCaptureDevice> = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as! Array<AVCaptureDevice> let devices: Array<AVCaptureDevice> = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as! Array<AVCaptureDevice>
for device in devices { for device in devices {
if device.position == position { if device.position == position {
...@@ -752,7 +716,8 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -752,7 +716,8 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
/** /**
:name: uniqueURL Creates a unique URL if possible.
- Returns: A NSURL if it is possible to create one.
*/ */
private func uniqueURL() -> NSURL? { private func uniqueURL() -> NSURL? {
do { do {
...@@ -762,7 +727,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate { ...@@ -762,7 +727,7 @@ public class CaptureSession: NSObject, AVCaptureFileOutputRecordingDelegate {
dateFormatter.timeStyle = .fullStyle dateFormatter.timeStyle = .fullStyle
return directory.appendingPathComponent(dateFormatter.string(from: NSDate() as Date) + ".mov") return directory.appendingPathComponent(dateFormatter.string(from: NSDate() as Date) + ".mov")
} catch let e as NSError { } catch let e as NSError {
delegate?.captureCreateMovieFileFailedWithError?(capture: self, error: e) delegate?.captureSessionCreateMovieFileFailedWithError?(captureSession: self, error: e)
} }
return nil return nil
} }
......
...@@ -433,9 +433,9 @@ public class CaptureView : MaterialView, UIGestureRecognizerDelegate { ...@@ -433,9 +433,9 @@ public class CaptureView : MaterialView, UIGestureRecognizerDelegate {
*/ */
@objc @objc
internal func handleTapToFocusGesture(recognizer: UITapGestureRecognizer) { internal func handleTapToFocusGesture(recognizer: UITapGestureRecognizer) {
if enableTapToFocus && captureSession.cameraSupportsTapToFocus { if enableTapToFocus && captureSession.isFocusPointOfInterestSupported {
let point: CGPoint = recognizer.location(in: self) let point: CGPoint = recognizer.location(in: self)
captureSession.focusAtPoint(point: previewView.captureDevicePointOfInterestForPoint(point: point)) captureSession.focus(point: previewView.captureDevicePointOfInterestForPoint(point: point))
animateTapLayer(layer: focusLayer!, point: point) animateTapLayer(layer: focusLayer!, point: point)
(delegate as? CaptureViewDelegate)?.captureViewDidTapToFocusAtPoint?(captureView: self, point: point) (delegate as? CaptureViewDelegate)?.captureViewDidTapToFocusAtPoint?(captureView: self, point: point)
} }
...@@ -447,9 +447,9 @@ public class CaptureView : MaterialView, UIGestureRecognizerDelegate { ...@@ -447,9 +447,9 @@ public class CaptureView : MaterialView, UIGestureRecognizerDelegate {
*/ */
@objc @objc
internal func handleTapToExposeGesture(recognizer: UITapGestureRecognizer) { internal func handleTapToExposeGesture(recognizer: UITapGestureRecognizer) {
if enableTapToExpose && captureSession.cameraSupportsTapToExpose { if enableTapToExpose && captureSession.isExposurePointOfInterestSupported {
let point: CGPoint = recognizer.location(in: self) let point: CGPoint = recognizer.location(in: self)
captureSession.exposeAtPoint(point: previewView.captureDevicePointOfInterestForPoint(point: point)) captureSession.expose(point: previewView.captureDevicePointOfInterestForPoint(point: point))
animateTapLayer(layer: exposureLayer!, point: point) animateTapLayer(layer: exposureLayer!, point: point)
(delegate as? CaptureViewDelegate)?.captureViewDidTapToExposeAtPoint?(captureView: self, point: point) (delegate as? CaptureViewDelegate)?.captureViewDidTapToExposeAtPoint?(captureView: self, point: point)
} }
...@@ -462,7 +462,7 @@ public class CaptureView : MaterialView, UIGestureRecognizerDelegate { ...@@ -462,7 +462,7 @@ public class CaptureView : MaterialView, UIGestureRecognizerDelegate {
@objc @objc
internal func handleTapToResetGesture(recognizer: UITapGestureRecognizer) { internal func handleTapToResetGesture(recognizer: UITapGestureRecognizer) {
if enableTapToReset { if enableTapToReset {
captureSession.resetFocusAndExposureModes() captureSession.reset()
let point: CGPoint = previewView.pointForCaptureDevicePointOfInterest(point: CGPoint(x: 0.5, y: 0.5)) let point: CGPoint = previewView.pointForCaptureDevicePointOfInterest(point: CGPoint(x: 0.5, y: 0.5))
animateTapLayer(layer: resetLayer!, point: point) animateTapLayer(layer: resetLayer!, point: point)
(delegate as? CaptureViewDelegate)?.captureViewDidTapToResetAtPoint?(captureView: self, point: point) (delegate as? CaptureViewDelegate)?.captureViewDidTapToResetAtPoint?(captureView: self, point: point)
......
...@@ -59,7 +59,7 @@ public class ControlView : MaterialView { ...@@ -59,7 +59,7 @@ public class ControlView : MaterialView {
/// A preset wrapper around interimSpace. /// A preset wrapper around interimSpace.
public var interimSpacePreset: InterimSpace = .none { public var interimSpacePreset: InterimSpace = .none {
didSet { didSet {
interimSpace = interimSpaceToValue(interimSpacePreset) interimSpace = InterimSpaceToValue(interimSpacePreset)
} }
} }
......
...@@ -156,7 +156,7 @@ public class Grid { ...@@ -156,7 +156,7 @@ public class Grid {
/// A preset wrapper around interimSpace. /// A preset wrapper around interimSpace.
public var interimSpacePreset: InterimSpace = .none { public var interimSpacePreset: InterimSpace = .none {
didSet { didSet {
interimSpace = interimSpaceToValue(interimSpacePreset) interimSpace = InterimSpaceToValue(interimSpacePreset)
} }
} }
...@@ -252,4 +252,4 @@ public extension UIView { ...@@ -252,4 +252,4 @@ public extension UIView {
associateObject(self, key: &GridKey, value: value) associateObject(self, key: &GridKey, value: value)
} }
} }
} }
\ No newline at end of file
...@@ -44,7 +44,7 @@ public enum InterimSpace { ...@@ -44,7 +44,7 @@ public enum InterimSpace {
} }
/// Converts the InterimSpace enum to a CGFloat value. /// Converts the InterimSpace enum to a CGFloat value.
public func interimSpaceToValue(interimSpace: InterimSpace) -> CGFloat { public func InterimSpaceToValue(interimSpace: InterimSpace) -> CGFloat {
switch interimSpace { switch interimSpace {
case .none: case .none:
return 0 return 0
......
...@@ -155,7 +155,7 @@ public class MaterialCollectionReusableView : UICollectionReusableView { ...@@ -155,7 +155,7 @@ public class MaterialCollectionReusableView : UICollectionReusableView {
/// A preset wrapper around interimSpace. /// A preset wrapper around interimSpace.
public var interimSpacePreset: InterimSpace = .none { public var interimSpacePreset: InterimSpace = .none {
didSet { didSet {
interimSpace = interimSpaceToValue(interimSpacePreset) interimSpace = InterimSpaceToValue(interimSpacePreset)
} }
} }
...@@ -606,4 +606,4 @@ public class MaterialCollectionReusableView : UICollectionReusableView { ...@@ -606,4 +606,4 @@ public class MaterialCollectionReusableView : UICollectionReusableView {
} }
} }
} }
} }
\ No newline at end of file
...@@ -104,7 +104,7 @@ public class MaterialCollectionView : UICollectionView { ...@@ -104,7 +104,7 @@ public class MaterialCollectionView : UICollectionView {
/// A preset wrapper around interimSpace. /// A preset wrapper around interimSpace.
public var interimSpacePreset: InterimSpace = .none { public var interimSpacePreset: InterimSpace = .none {
didSet { didSet {
interimSpace = interimSpaceToValue(interimSpacePreset) interimSpace = InterimSpaceToValue(interimSpacePreset)
} }
} }
...@@ -163,4 +163,4 @@ public class MaterialCollectionView : UICollectionView { ...@@ -163,4 +163,4 @@ public class MaterialCollectionView : UICollectionView {
backgroundColor = Color.clear backgroundColor = Color.clear
contentInset = UIEdgeInsetsZero contentInset = UIEdgeInsetsZero
} }
} }
\ No newline at end of file
...@@ -155,7 +155,7 @@ public class MaterialCollectionViewCell : UICollectionViewCell { ...@@ -155,7 +155,7 @@ public class MaterialCollectionViewCell : UICollectionViewCell {
/// A preset wrapper around interimSpace. /// A preset wrapper around interimSpace.
public var interimSpacePreset: InterimSpace = .none { public var interimSpacePreset: InterimSpace = .none {
didSet { didSet {
interimSpace = interimSpaceToValue(interimSpacePreset) interimSpace = InterimSpaceToValue(interimSpacePreset)
} }
} }
...@@ -605,4 +605,4 @@ public class MaterialCollectionViewCell : UICollectionViewCell { ...@@ -605,4 +605,4 @@ public class MaterialCollectionViewCell : UICollectionViewCell {
} }
} }
} }
} }
\ No newline at end of file
...@@ -62,7 +62,7 @@ public class MaterialCollectionViewLayout : UICollectionViewLayout { ...@@ -62,7 +62,7 @@ public class MaterialCollectionViewLayout : UICollectionViewLayout {
/// A preset wrapper around interimSpace. /// A preset wrapper around interimSpace.
public var interimSpacePreset: InterimSpace = .none { public var interimSpacePreset: InterimSpace = .none {
didSet { didSet {
interimSpace = interimSpaceToValue(interimSpacePreset) interimSpace = InterimSpaceToValue(interimSpacePreset)
} }
} }
...@@ -159,4 +159,4 @@ public class MaterialCollectionViewLayout : UICollectionViewLayout { ...@@ -159,4 +159,4 @@ public class MaterialCollectionViewLayout : UICollectionViewLayout {
contentSize = CGSizeMake(offset.x, collectionView!.bounds.height) contentSize = CGSizeMake(offset.x, collectionView!.bounds.height)
} }
} }
} }
\ No newline at end of file
...@@ -51,7 +51,7 @@ public class Menu { ...@@ -51,7 +51,7 @@ public class Menu {
/// A preset wrapper around interimSpace. /// A preset wrapper around interimSpace.
public var interimSpacePreset: InterimSpace = .none { public var interimSpacePreset: InterimSpace = .none {
didSet { didSet {
interimSpace = interimSpaceToValue(interimSpacePreset) interimSpace = InterimSpaceToValue(interimSpacePreset)
} }
} }
......
...@@ -78,7 +78,7 @@ public class NavigationBar : UINavigationBar { ...@@ -78,7 +78,7 @@ public class NavigationBar : UINavigationBar {
/// A preset wrapper around interimSpace. /// A preset wrapper around interimSpace.
public var interimSpacePreset: InterimSpace = .none { public var interimSpacePreset: InterimSpace = .none {
didSet { didSet {
interimSpace = interimSpaceToValue(interimSpacePreset) interimSpace = InterimSpaceToValue(interimSpacePreset)
} }
} }
...@@ -475,4 +475,4 @@ public class NavigationBar : UINavigationBar { ...@@ -475,4 +475,4 @@ public class NavigationBar : UINavigationBar {
item.contentView!.grid.axis.direction = .Vertical item.contentView!.grid.axis.direction = .Vertical
return item.contentView! return item.contentView!
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment