Compare commits

...

4 Commits
master ... zoom

Author SHA1 Message Date
Ricardo Torrão c1d6fd5abf Saves still images with Zoom 2016-01-29 18:21:02 +00:00
Ricardo Torrão 5f94c9b898 Pinch to Zoom 2016-01-26 16:05:21 +00:00
Ricardo Torrão 93c9920a65 Merge branch 'zoom' of github.com:imaginary-cloud/CameraManager into zoom
# Conflicts:
#	camera.xcodeproj/project.xcworkspace/xcuserdata/nataliaterlecka.xcuserdatad/UserInterfaceState.xcuserstate
#	camera/CameraManager.swift
2016-01-26 10:07:54 +00:00
Natalia Terlecka eb4e77d2bb cameraIsReady property and addPreviewLayerToView competition block. 2015-12-24 09:52:39 +01:00
5 changed files with 145 additions and 49 deletions

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9531" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/> <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies> </dependencies>
<objects> <objects>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="bhK-VL-qY4"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="bhK-VL-qY4">
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/> <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies> </dependencies>
<scenes> <scenes>

View File

@ -31,25 +31,25 @@ public enum CameraOutputQuality: Int {
} }
/// Class for handling iDevices custom camera usage /// Class for handling iDevices custom camera usage
public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate { public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate, UIGestureRecognizerDelegate {
// MARK: - Public properties // MARK: - Public properties
/// Capture session to customize camera settings. /// Capture session to customize camera settings.
public var captureSession: AVCaptureSession? public var captureSession: AVCaptureSession?
/// Property to determine if the manager should show the error for the user. If you want to show the errors yourself set this to false. If you want to add custom error UI set showErrorBlock property. Default value is false. /// Property to determine if the manager should show the error for the user. If you want to show the errors yourself set this to false. If you want to add custom error UI set showErrorBlock property. Default value is false.
public var showErrorsToUsers = false public var showErrorsToUsers = false
/// Property to determine if the manager should show the camera permission popup immediatly when it's needed or you want to show it manually. Default value is true. Be carful cause using the camera requires permission, if you set this value to false and don't ask manually you won't be able to use the camera. /// Property to determine if the manager should show the camera permission popup immediatly when it's needed or you want to show it manually. Default value is true. Be carful cause using the camera requires permission, if you set this value to false and don't ask manually you won't be able to use the camera.
public var showAccessPermissionPopupAutomatically = true public var showAccessPermissionPopupAutomatically = true
/// A block creating UI to present error message to the user. This can be customised to be presented on the Window root view controller, or to pass in the viewController which will present the UIAlertController, for example. /// A block creating UI to present error message to the user. This can be customised to be presented on the Window root view controller, or to pass in the viewController which will present the UIAlertController, for example.
public var showErrorBlock:(erTitle: String, erMessage: String) -> Void = { (erTitle: String, erMessage: String) -> Void in public var showErrorBlock:(erTitle: String, erMessage: String) -> Void = { (erTitle: String, erMessage: String) -> Void in
// var alertController = UIAlertController(title: erTitle, message: erMessage, preferredStyle: .Alert) // var alertController = UIAlertController(title: erTitle, message: erMessage, preferredStyle: .Alert)
// alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (alertAction) -> Void in })) // alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (alertAction) -> Void in }))
// //
// if let topController = UIApplication.sharedApplication().keyWindow?.rootViewController { // if let topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
// topController.presentViewController(alertController, animated: true, completion:nil) // topController.presentViewController(alertController, animated: true, completion:nil)
// } // }
@ -58,6 +58,9 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
/// Property to determine if manager should write the resources to the phone library. Default value is true. /// Property to determine if manager should write the resources to the phone library. Default value is true.
public var writeFilesToPhoneLibrary = true public var writeFilesToPhoneLibrary = true
/// Property to determine if manager allows zoom. Default value is true.
public var enableZoom = true
/// Property to determine if manager should follow device orientation. Default value is true. /// Property to determine if manager should follow device orientation. Default value is true.
public var shouldRespondToOrientationChanges = true { public var shouldRespondToOrientationChanges = true {
didSet { didSet {
@ -68,14 +71,14 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} }
} }
/// The Bool property to determine if the camera is ready to use. /// The Bool property to determine if the camera is ready to use.
public var cameraIsReady: Bool { public var cameraIsReady: Bool {
get { get {
return cameraIsSetup return cameraIsSetup
} }
} }
/// The Bool property to determine if current device has front camera. /// The Bool property to determine if current device has front camera.
public var hasFrontCamera: Bool = { public var hasFrontCamera: Bool = {
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
@ -87,7 +90,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
return false return false
}() }()
/// The Bool property to determine if current device has flash. /// The Bool property to determine if current device has flash.
public var hasFlash: Bool = { public var hasFlash: Bool = {
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
@ -99,7 +102,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
return false return false
}() }()
/// Property to change camera device between front and back. /// Property to change camera device between front and back.
public var cameraDevice = CameraDevice.Back { public var cameraDevice = CameraDevice.Back {
didSet { didSet {
@ -139,18 +142,19 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
if cameraIsSetup { if cameraIsSetup {
if cameraOutputMode != oldValue { if cameraOutputMode != oldValue {
_setupOutputMode(cameraOutputMode, oldCameraOutputMode: oldValue) _setupOutputMode(cameraOutputMode, oldCameraOutputMode: oldValue)
_setupMaxZoom()
} }
} }
} }
} }
/// Property to check video recording duration when in progress /// Property to check video recording duration when in progress
public var recordedDuration : CMTime { return movieOutput?.recordedDuration ?? kCMTimeZero } public var recordedDuration : CMTime { return movieOutput?.recordedDuration ?? kCMTimeZero }
/// Property to check video recording file size when in progress /// Property to check video recording file size when in progress
public var recordedFileSize : Int64 { return movieOutput?.recordedFileSize ?? 0 } public var recordedFileSize : Int64 { return movieOutput?.recordedFileSize ?? 0 }
// MARK: - Private properties // MARK: - Private properties
private weak var embedingView: UIView? private weak var embedingView: UIView?
@ -162,16 +166,16 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice] let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice]
return devices.filter{$0.position == .Front}.first return devices.filter{$0.position == .Front}.first
}() }()
private lazy var backCameraDevice: AVCaptureDevice? = { private lazy var backCameraDevice: AVCaptureDevice? = {
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice] let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice]
return devices.filter{$0.position == .Back}.first return devices.filter{$0.position == .Back}.first
}() }()
private lazy var mic: AVCaptureDevice? = { private lazy var mic: AVCaptureDevice? = {
return AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeAudio) return AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeAudio)
}() }()
private var stillImageOutput: AVCaptureStillImageOutput? private var stillImageOutput: AVCaptureStillImageOutput?
private var movieOutput: AVCaptureMovieFileOutput? private var movieOutput: AVCaptureMovieFileOutput?
private var previewLayer: AVCaptureVideoPreviewLayer? private var previewLayer: AVCaptureVideoPreviewLayer?
@ -188,9 +192,14 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} catch { } } catch { }
} }
return NSURL(string: tempPath)! return NSURL(string: tempPath)!
}() }()
private var pinchToZoom: UIPinchGestureRecognizer?
private var zoomScale: CGFloat = 1.0
private var beginZoomScale: CGFloat = 1.0
private var maxZoomFactor: CGFloat = 1.0
// MARK: - CameraManager // MARK: - CameraManager
/** /**
@ -199,7 +208,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
:param: view The view you want to add the preview layer to :param: view The view you want to add the preview layer to
:param: cameraOutputMode The mode you want capturesession to run image / video / video and microphone :param: cameraOutputMode The mode you want capturesession to run image / video / video and microphone
:param: completition Optional completition block :param: completition Optional completition block
:returns: Current state of the camera: Ready / AccessDenied / NoDeviceFound / NotDetermined. :returns: Current state of the camera: Ready / AccessDenied / NoDeviceFound / NotDetermined.
*/ */
public func addPreviewLayerToView(view: UIView) -> CameraState { public func addPreviewLayerToView(view: UIView) -> CameraState {
@ -236,7 +245,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
/** /**
Asks the user for camera permissions. Only works if the permissions are not yet determined. Note that it'll also automaticaly ask about the microphone permissions if you selected VideoWithMic output. Asks the user for camera permissions. Only works if the permissions are not yet determined. Note that it'll also automaticaly ask about the microphone permissions if you selected VideoWithMic output.
:param: completition Completition block with the result of permission request :param: completition Completition block with the result of permission request
*/ */
public func askUserForCameraPermissions(completition: Bool -> Void) { public func askUserForCameraPermissions(completition: Bool -> Void) {
@ -340,7 +349,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
imageCompletition(UIImage(data: imageData), nil) imageCompletition(UIImage(data: imageData), nil)
} }
}) })
}) })
} else { } else {
_show(NSLocalizedString("Capture session output mode video", comment:""), message: NSLocalizedString("I can't take any picture", comment:"")) _show(NSLocalizedString("Capture session output mode video", comment:""), message: NSLocalizedString("I can't take any picture", comment:""))
@ -375,33 +384,33 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
/** /**
Current camera status. Current camera status.
:returns: Current state of the camera: Ready / AccessDenied / NoDeviceFound / NotDetermined :returns: Current state of the camera: Ready / AccessDenied / NoDeviceFound / NotDetermined
*/ */
public func currentCameraStatus() -> CameraState { public func currentCameraStatus() -> CameraState {
return _checkIfCameraIsAvailable() return _checkIfCameraIsAvailable()
} }
/** /**
Change current flash mode to next value from available ones. Change current flash mode to next value from available ones.
:returns: Current flash mode: Off / On / Auto :returns: Current flash mode: Off / On / Auto
*/ */
public func changeFlashMode() -> CameraFlashMode { public func changeFlashMode() -> CameraFlashMode {
flashMode = CameraFlashMode(rawValue: (flashMode.rawValue+1)%3)! flashMode = CameraFlashMode(rawValue: (flashMode.rawValue+1)%3)!
return flashMode return flashMode
} }
/** /**
Change current output quality mode to next value from available ones. Change current output quality mode to next value from available ones.
:returns: Current quality mode: Low / Medium / High :returns: Current quality mode: Low / Medium / High
*/ */
public func changeQualityMode() -> CameraOutputQuality { public func changeQualityMode() -> CameraOutputQuality {
cameraOutputQuality = CameraOutputQuality(rawValue: (cameraOutputQuality.rawValue+1)%3)! cameraOutputQuality = CameraOutputQuality(rawValue: (cameraOutputQuality.rawValue+1)%3)!
return cameraOutputQuality return cameraOutputQuality
} }
// MARK: - AVCaptureFileOutputRecordingDelegate // MARK: - AVCaptureFileOutputRecordingDelegate
public func captureOutput(captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) { public func captureOutput(captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) {
@ -435,9 +444,48 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} }
} }
// MARK: - UIGestureRecognizerDelegate
public func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer.isKindOfClass(UIPinchGestureRecognizer) {
beginZoomScale = zoomScale;
}
return true
}
func _handlePinchGesture(pinchRecognizer: UIPinchGestureRecognizer) {
var allTouchesAreOnThePreviewLayer = true
let numTouches = pinchRecognizer.numberOfTouches();
for index in 0..<numTouches {
let location: CGPoint = pinchRecognizer.locationOfTouch(index, inView: embedingView)
let convertedLocation: CGPoint = (embedingView?.convertPoint(location, fromCoordinateSpace: (embedingView?.superview)!))!
if ((embedingView?.pointInside(convertedLocation, withEvent: nil)) == nil) {
allTouchesAreOnThePreviewLayer = false
break
}
}
if allTouchesAreOnThePreviewLayer {
_updateZoomScale(pinchRecognizer.scale)
_applyZoomScale()
}
}
// MARK: - CameraManager() // MARK: - CameraManager()
private func _updateZoomScale(scale: CGFloat) {
zoomScale = max(1.0, min(beginZoomScale * scale, maxZoomFactor))
}
private func _updateTorch(flashMode: CameraFlashMode) { private func _updateTorch(flashMode: CameraFlashMode) {
captureSession?.beginConfiguration() captureSession?.beginConfiguration()
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
@ -458,7 +506,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
captureSession?.commitConfiguration() captureSession?.commitConfiguration()
} }
private func _executeVideoCompletitionWithURL(url: NSURL?, error: NSError?) { private func _executeVideoCompletitionWithURL(url: NSURL?, error: NSError?) {
if let validCompletition = videoCompletition { if let validCompletition = videoCompletition {
validCompletition(videoURL: url, error: error) validCompletition(videoURL: url, error: error)
@ -473,7 +521,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
shouldReinitializeMovieOutput = shouldReinitializeMovieOutput || !connection.active shouldReinitializeMovieOutput = shouldReinitializeMovieOutput || !connection.active
} }
} }
if shouldReinitializeMovieOutput { if shouldReinitializeMovieOutput {
movieOutput = AVCaptureMovieFileOutput() movieOutput = AVCaptureMovieFileOutput()
movieOutput!.movieFragmentInterval = kCMTimeInvalid movieOutput!.movieFragmentInterval = kCMTimeInvalid
@ -484,7 +532,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
return movieOutput! return movieOutput!
} }
private func _getStillImageOutput() -> AVCaptureStillImageOutput { private func _getStillImageOutput() -> AVCaptureStillImageOutput {
var shouldReinitializeStillImageOutput = stillImageOutput == nil var shouldReinitializeStillImageOutput = stillImageOutput == nil
if !shouldReinitializeStillImageOutput { if !shouldReinitializeStillImageOutput {
@ -494,19 +542,22 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
if shouldReinitializeStillImageOutput { if shouldReinitializeStillImageOutput {
stillImageOutput = AVCaptureStillImageOutput() stillImageOutput = AVCaptureStillImageOutput()
captureSession?.beginConfiguration() captureSession?.beginConfiguration()
captureSession?.addOutput(stillImageOutput) captureSession?.addOutput(stillImageOutput)
captureSession?.commitConfiguration() captureSession?.commitConfiguration()
} }
stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo)?.videoScaleAndCropFactor = zoomScale
return stillImageOutput! return stillImageOutput!
} }
@objc private func _orientationChanged() { @objc private func _orientationChanged() {
var currentConnection: AVCaptureConnection?; var currentConnection: AVCaptureConnection?;
switch cameraOutputMode { switch cameraOutputMode {
case .StillImage: case .StillImage:
currentConnection = stillImageOutput?.connectionWithMediaType(AVMediaTypeVideo) currentConnection = _getStillImageOutput().connectionWithMediaType(AVMediaTypeVideo)
case .VideoOnly, .VideoWithMic: case .VideoOnly, .VideoWithMic:
currentConnection = _getMovieOutput().connectionWithMediaType(AVMediaTypeVideo) currentConnection = _getMovieOutput().connectionWithMediaType(AVMediaTypeVideo)
} }
@ -547,12 +598,13 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
private func _setupCamera(completition: Void -> Void) { private func _setupCamera(completition: Void -> Void) {
captureSession = AVCaptureSession() captureSession = AVCaptureSession()
dispatch_async(sessionQueue, { dispatch_async(sessionQueue, {
if let validCaptureSession = self.captureSession { if let validCaptureSession = self.captureSession {
validCaptureSession.beginConfiguration() validCaptureSession.beginConfiguration()
validCaptureSession.sessionPreset = AVCaptureSessionPresetHigh validCaptureSession.sessionPreset = AVCaptureSessionPresetHigh
self._updateCameraDevice(self.cameraDevice) self._updateCameraDevice(self.cameraDevice)
self._setupPinchToZoom()
self._setupOutputs() self._setupOutputs()
self._setupOutputMode(self.cameraOutputMode, oldCameraOutputMode: nil) self._setupOutputMode(self.cameraOutputMode, oldCameraOutputMode: nil)
self._setupPreviewLayer() self._setupPreviewLayer()
@ -563,7 +615,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
self._startFollowingDeviceOrientation() self._startFollowingDeviceOrientation()
self.cameraIsSetup = true self.cameraIsSetup = true
self._orientationChanged() self._orientationChanged()
completition() completition()
} }
}) })
@ -585,6 +637,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
private func _addPreviewLayerToView(view: UIView) { private func _addPreviewLayerToView(view: UIView) {
embedingView = view embedingView = view
dispatch_async(dispatch_get_main_queue(), { () -> Void in dispatch_async(dispatch_get_main_queue(), { () -> Void in
guard let _ = self.previewLayer else { guard let _ = self.previewLayer else {
return return
@ -614,15 +667,29 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} }
private func _setupMaxZoom() {
if cameraDevice == .Back {
if let maxZoom = backCameraDevice?.activeFormat.videoMaxZoomFactor {
maxZoomFactor = maxZoom
}
}
else {
if let maxZoom = frontCameraDevice?.activeFormat.videoMaxZoomFactor {
maxZoomFactor = maxZoom
}
}
}
private func _setupOutputMode(newCameraOutputMode: CameraOutputMode, oldCameraOutputMode: CameraOutputMode?) { private func _setupOutputMode(newCameraOutputMode: CameraOutputMode, oldCameraOutputMode: CameraOutputMode?) {
captureSession?.beginConfiguration() captureSession?.beginConfiguration()
if let cameraOutputToRemove = oldCameraOutputMode { if let cameraOutputToRemove = oldCameraOutputMode {
// remove current setting // remove current setting
switch cameraOutputToRemove { switch cameraOutputToRemove {
case .StillImage: case .StillImage:
if let validStillImageOutput = stillImageOutput { if let validStillImageOutput = stillImageOutput {
captureSession?.removeOutput(validStillImageOutput) captureSession?.removeOutput(validStillImageOutput)
_removePinchToZoom()
} }
case .VideoOnly, .VideoWithMic: case .VideoOnly, .VideoWithMic:
if let validMovieOutput = movieOutput { if let validMovieOutput = movieOutput {
@ -633,7 +700,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} }
} }
// configure new devices // configure new devices
switch newCameraOutputMode { switch newCameraOutputMode {
case .StillImage: case .StillImage:
@ -642,10 +709,11 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
if let validStillImageOutput = stillImageOutput { if let validStillImageOutput = stillImageOutput {
captureSession?.addOutput(validStillImageOutput) captureSession?.addOutput(validStillImageOutput)
_addPinchToZoom()
} }
case .VideoOnly, .VideoWithMic: case .VideoOnly, .VideoWithMic:
captureSession?.addOutput(_getMovieOutput()) captureSession?.addOutput(_getMovieOutput())
if newCameraOutputMode == .VideoWithMic { if newCameraOutputMode == .VideoWithMic {
if let validMic = _deviceInputFromDevice(mic) { if let validMic = _deviceInputFromDevice(mic) {
captureSession?.addInput(validMic) captureSession?.addInput(validMic)
@ -656,7 +724,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
_updateCameraQualityMode(cameraOutputQuality) _updateCameraQualityMode(cameraOutputQuality)
_orientationChanged() _orientationChanged()
} }
private func _setupOutputs() { private func _setupOutputs() {
if (stillImageOutput == nil) { if (stillImageOutput == nil) {
stillImageOutput = AVCaptureStillImageOutput() stillImageOutput = AVCaptureStillImageOutput()
@ -676,12 +744,12 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
} }
} }
private func _updateCameraDevice(deviceType: CameraDevice) { private func _updateCameraDevice(deviceType: CameraDevice) {
if let validCaptureSession = captureSession { if let validCaptureSession = captureSession {
validCaptureSession.beginConfiguration() validCaptureSession.beginConfiguration()
let inputs = validCaptureSession.inputs as! [AVCaptureInput] let inputs = validCaptureSession.inputs as! [AVCaptureInput]
for input in inputs { for input in inputs {
if let deviceInput = input as? AVCaptureDeviceInput { if let deviceInput = input as? AVCaptureDeviceInput {
if deviceInput.device == backCameraDevice && cameraDevice == .Front { if deviceInput.device == backCameraDevice && cameraDevice == .Front {
@ -712,7 +780,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
validCaptureSession.commitConfiguration() validCaptureSession.commitConfiguration()
} }
} }
private func _updateFlasMode(flashMode: CameraFlashMode) { private func _updateFlasMode(flashMode: CameraFlashMode) {
captureSession?.beginConfiguration() captureSession?.beginConfiguration()
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
@ -763,7 +831,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
private func _removeMicInput() { private func _removeMicInput() {
guard let inputs = captureSession?.inputs as? [AVCaptureInput] else { return } guard let inputs = captureSession?.inputs as? [AVCaptureInput] else { return }
for input in inputs { for input in inputs {
if let deviceInput = input as? AVCaptureDeviceInput { if let deviceInput = input as? AVCaptureDeviceInput {
if deviceInput.device == mic { if deviceInput.device == mic {
@ -773,7 +841,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
} }
} }
} }
private func _show(title: String, message: String) { private func _show(title: String, message: String) {
if showErrorsToUsers { if showErrorsToUsers {
dispatch_async(dispatch_get_main_queue(), { () -> Void in dispatch_async(dispatch_get_main_queue(), { () -> Void in
@ -781,7 +849,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
}) })
} }
} }
private func _deviceInputFromDevice(device: AVCaptureDevice?) -> AVCaptureDeviceInput? { private func _deviceInputFromDevice(device: AVCaptureDevice?) -> AVCaptureDeviceInput? {
guard let validDevice = device else { return nil } guard let validDevice = device else { return nil }
do { do {
@ -791,6 +859,28 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate {
return nil return nil
} }
} }
private func _setupPinchToZoom() {
pinchToZoom = UIPinchGestureRecognizer(target: self, action: "_handlePinchGesture:")
pinchToZoom!.delegate = self
}
private func _addPinchToZoom() {
embedingView?.addGestureRecognizer(pinchToZoom!)
}
private func _removePinchToZoom() {
embedingView?.removeGestureRecognizer(pinchToZoom!)
}
private func _applyZoomScale() {
let affineTransform = CGAffineTransformMakeScale(zoomScale, zoomScale)
CATransaction.begin()
CATransaction.setAnimationDuration(0.025)
embedingView?.transform = affineTransform
CATransaction.commit()
}
deinit { deinit {
stopAndRemoveCaptureSession() stopAndRemoveCaptureSession()

View File

@ -59,6 +59,11 @@
"idiom" : "ipad", "idiom" : "ipad",
"size" : "76x76", "size" : "76x76",
"scale" : "2x" "scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
} }
], ],
"info" : { "info" : {