mirror of
https://github.com/samsonjs/SwiftyCam.git
synced 2026-03-25 09:05:52 +00:00
Address warnings, rip out photos, and make the button responsive
This commit is contained in:
parent
707bf2292c
commit
54a288b661
8 changed files with 56 additions and 371 deletions
|
|
@ -25,7 +25,6 @@
|
||||||
1675A98F1E00A74A00B80903 /* SwiftyCamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A98B1E00A74A00B80903 /* SwiftyCamViewController.swift */; };
|
1675A98F1E00A74A00B80903 /* SwiftyCamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A98B1E00A74A00B80903 /* SwiftyCamViewController.swift */; };
|
||||||
1675A9901E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A98C1E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift */; };
|
1675A9901E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A98C1E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift */; };
|
||||||
168505E81E288B4C005B4537 /* VideoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 168505E71E288B4C005B4537 /* VideoViewController.swift */; };
|
168505E81E288B4C005B4537 /* VideoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 168505E71E288B4C005B4537 /* VideoViewController.swift */; };
|
||||||
168505EA1E288D80005B4537 /* PhotoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 168505E91E288D80005B4537 /* PhotoViewController.swift */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
|
@ -46,7 +45,6 @@
|
||||||
1675A98B1E00A74A00B80903 /* SwiftyCamViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyCamViewController.swift; path = ../../Source/SwiftyCamViewController.swift; sourceTree = "<group>"; };
|
1675A98B1E00A74A00B80903 /* SwiftyCamViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyCamViewController.swift; path = ../../Source/SwiftyCamViewController.swift; sourceTree = "<group>"; };
|
||||||
1675A98C1E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyCamViewControllerDelegate.swift; path = ../../Source/SwiftyCamViewControllerDelegate.swift; sourceTree = "<group>"; };
|
1675A98C1E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyCamViewControllerDelegate.swift; path = ../../Source/SwiftyCamViewControllerDelegate.swift; sourceTree = "<group>"; };
|
||||||
168505E71E288B4C005B4537 /* VideoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoViewController.swift; sourceTree = "<group>"; };
|
168505E71E288B4C005B4537 /* VideoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoViewController.swift; sourceTree = "<group>"; };
|
||||||
168505E91E288D80005B4537 /* PhotoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoViewController.swift; sourceTree = "<group>"; };
|
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -102,7 +100,6 @@
|
||||||
1675A9771E00A68300B80903 /* ViewController.swift */,
|
1675A9771E00A68300B80903 /* ViewController.swift */,
|
||||||
16298B551E2703DC0056D413 /* SwiftyRecordButton.swift */,
|
16298B551E2703DC0056D413 /* SwiftyRecordButton.swift */,
|
||||||
168505E71E288B4C005B4537 /* VideoViewController.swift */,
|
168505E71E288B4C005B4537 /* VideoViewController.swift */,
|
||||||
168505E91E288D80005B4537 /* PhotoViewController.swift */,
|
|
||||||
1675A9791E00A68300B80903 /* Main.storyboard */,
|
1675A9791E00A68300B80903 /* Main.storyboard */,
|
||||||
1675A97C1E00A68300B80903 /* Assets.xcassets */,
|
1675A97C1E00A68300B80903 /* Assets.xcassets */,
|
||||||
1675A97E1E00A68300B80903 /* LaunchScreen.storyboard */,
|
1675A97E1E00A68300B80903 /* LaunchScreen.storyboard */,
|
||||||
|
|
@ -255,7 +252,6 @@
|
||||||
168505E81E288B4C005B4537 /* VideoViewController.swift in Sources */,
|
168505E81E288B4C005B4537 /* VideoViewController.swift in Sources */,
|
||||||
1675A9761E00A68300B80903 /* AppDelegate.swift in Sources */,
|
1675A9761E00A68300B80903 /* AppDelegate.swift in Sources */,
|
||||||
1675A98F1E00A74A00B80903 /* SwiftyCamViewController.swift in Sources */,
|
1675A98F1E00A74A00B80903 /* SwiftyCamViewController.swift in Sources */,
|
||||||
168505EA1E288D80005B4537 /* PhotoViewController.swift in Sources */,
|
|
||||||
056AAB091F97CB1700F6A978 /* Orientation.swift in Sources */,
|
056AAB091F97CB1700F6A978 /* Orientation.swift in Sources */,
|
||||||
16298B561E2703DC0056D413 /* SwiftyRecordButton.swift in Sources */,
|
16298B561E2703DC0056D413 /* SwiftyRecordButton.swift in Sources */,
|
||||||
1675A98D1E00A74A00B80903 /* PreviewView.swift in Sources */,
|
1675A98D1E00A74A00B80903 /* PreviewView.swift in Sources */,
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/*Copyright (c) 2016, Andrew Walz.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
|
||||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
||||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
class PhotoViewController: UIViewController {
|
|
||||||
|
|
||||||
override var prefersStatusBarHidden: Bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private var backgroundImage: UIImage
|
|
||||||
|
|
||||||
init(image: UIImage) {
|
|
||||||
self.backgroundImage = image
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad()
|
|
||||||
self.view.backgroundColor = UIColor.gray
|
|
||||||
let backgroundImageView = UIImageView(frame: view.frame)
|
|
||||||
backgroundImageView.contentMode = UIView.ContentMode.scaleAspectFit
|
|
||||||
backgroundImageView.image = backgroundImage
|
|
||||||
view.addSubview(backgroundImageView)
|
|
||||||
let cancelButton = UIButton(frame: CGRect(x: 10.0, y: 10.0, width: 30.0, height: 30.0))
|
|
||||||
cancelButton.setImage(#imageLiteral(resourceName: "cancel"), for: UIControl.State())
|
|
||||||
cancelButton.addTarget(self, action: #selector(cancel), for: .touchUpInside)
|
|
||||||
view.addSubview(cancelButton)
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func cancel() {
|
|
||||||
dismiss(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -62,10 +62,7 @@ class VideoViewController: UIViewController {
|
||||||
|
|
||||||
// Allow background audio to continue to play
|
// Allow background audio to continue to play
|
||||||
do {
|
do {
|
||||||
if #available(iOS 10.0, *) {
|
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: .default, options: [])
|
||||||
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: .default, options: [])
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
} catch let error as NSError {
|
} catch let error as NSError {
|
||||||
print(error)
|
print(error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ class ViewController: SwiftyCamViewController, SwiftyCamViewControllerDelegate {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
shouldPrompToAppSettings = true
|
shouldPrompToAppSettings = true
|
||||||
cameraDelegate = self
|
cameraDelegate = self
|
||||||
maximumVideoDuration = 10.0
|
|
||||||
shouldUseDeviceOrientation = true
|
shouldUseDeviceOrientation = true
|
||||||
allowAutoRotate = true
|
allowAutoRotate = true
|
||||||
audioEnabled = true
|
audioEnabled = true
|
||||||
|
|
@ -56,11 +55,6 @@ class ViewController: SwiftyCamViewController, SwiftyCamViewControllerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didTake photo: UIImage) {
|
|
||||||
let newVC = PhotoViewController(image: photo)
|
|
||||||
self.present(newVC, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
|
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
|
||||||
print("Did Begin Recording")
|
print("Did Begin Recording")
|
||||||
captureButton.growButton()
|
captureButton.growButton()
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,8 @@ class Orientation {
|
||||||
return AVCaptureVideoOrientation.landscapeRight
|
return AVCaptureVideoOrientation.landscapeRight
|
||||||
case .portraitUpsideDown:
|
case .portraitUpsideDown:
|
||||||
return AVCaptureVideoOrientation.portraitUpsideDown
|
return AVCaptureVideoOrientation.portraitUpsideDown
|
||||||
|
@unknown default:
|
||||||
|
return .portrait
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,33 +20,21 @@ import UIKit
|
||||||
|
|
||||||
/// Delegate for SwiftyCamButton
|
/// Delegate for SwiftyCamButton
|
||||||
|
|
||||||
public protocol SwiftyCamButtonDelegate: class {
|
public protocol SwiftyCamButtonDelegate: AnyObject {
|
||||||
|
|
||||||
/// Called when UITapGestureRecognizer begins
|
/// Called when the button is first pressed
|
||||||
|
|
||||||
func buttonWasTapped()
|
|
||||||
|
|
||||||
/// Called When UILongPressGestureRecognizer enters UIGestureRecognizerState.began
|
|
||||||
|
|
||||||
func buttonDidBeginLongPress()
|
|
||||||
|
|
||||||
/// Called When UILongPressGestureRecognizer enters UIGestureRecognizerState.end
|
|
||||||
|
|
||||||
func buttonDidEndLongPress()
|
func buttonDidBeginPress()
|
||||||
|
|
||||||
/// Called when the maximum duration is reached
|
/// Called when the button is released
|
||||||
|
|
||||||
func longPressDidReachMaximumDuration()
|
func buttonDidEndPress()
|
||||||
|
|
||||||
/// Sets the maximum duration of the video recording
|
|
||||||
|
|
||||||
func setMaxiumVideoDuration() -> Double
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Public View Declaration
|
// MARK: Public View Declaration
|
||||||
|
|
||||||
|
|
||||||
/// UIButton Subclass for Capturing Photo and Video with SwiftyCamViewController
|
/// UIButton Subclass for Capturing Video with SwiftyCamViewController
|
||||||
|
|
||||||
open class SwiftyCamButton: UIButton {
|
open class SwiftyCamButton: UIButton {
|
||||||
|
|
||||||
|
|
@ -58,84 +46,27 @@ open class SwiftyCamButton: UIButton {
|
||||||
|
|
||||||
public var buttonEnabled = true
|
public var buttonEnabled = true
|
||||||
|
|
||||||
/// Maximum duration variable
|
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
super.touchesBegan(touches, with: event)
|
||||||
fileprivate var timer : Timer?
|
|
||||||
|
|
||||||
/// Initialization Declaration
|
|
||||||
|
|
||||||
override public init(frame: CGRect) {
|
|
||||||
super.init(frame: frame)
|
|
||||||
createGestureRecognizers()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialization Declaration
|
|
||||||
|
|
||||||
|
if buttonEnabled {
|
||||||
required public init?(coder aDecoder: NSCoder) {
|
delegate?.buttonDidBeginPress()
|
||||||
super.init(coder: aDecoder)
|
|
||||||
createGestureRecognizers()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// UITapGestureRecognizer Function
|
|
||||||
|
|
||||||
@objc fileprivate func Tap() {
|
|
||||||
guard buttonEnabled == true else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate?.buttonWasTapped()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// UILongPressGestureRecognizer Function
|
|
||||||
@objc fileprivate func LongPress(_ sender:UILongPressGestureRecognizer!) {
|
|
||||||
guard buttonEnabled == true else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch sender.state {
|
|
||||||
case .began:
|
|
||||||
delegate?.buttonDidBeginLongPress()
|
|
||||||
startTimer()
|
|
||||||
case .cancelled, .ended, .failed:
|
|
||||||
invalidateTimer()
|
|
||||||
delegate?.buttonDidEndLongPress()
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Timer Finished
|
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
super.touchesEnded(touches, with: event)
|
||||||
@objc fileprivate func timerFinished() {
|
|
||||||
invalidateTimer()
|
if buttonEnabled {
|
||||||
delegate?.longPressDidReachMaximumDuration()
|
delegate?.buttonDidEndPress()
|
||||||
}
|
|
||||||
|
|
||||||
/// Start Maximum Duration Timer
|
|
||||||
|
|
||||||
fileprivate func startTimer() {
|
|
||||||
if let duration = delegate?.setMaxiumVideoDuration() {
|
|
||||||
//Check if duration is set, and greater than zero
|
|
||||||
if duration != 0.0 && duration > 0.0 {
|
|
||||||
timer = Timer.scheduledTimer(timeInterval: duration, target: self, selector: #selector(SwiftyCamButton.timerFinished), userInfo: nil, repeats: false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// End timer if UILongPressGestureRecognizer is ended before time has ended
|
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
super.touchesCancelled(touches, with: event)
|
||||||
fileprivate func invalidateTimer() {
|
|
||||||
timer?.invalidate()
|
if buttonEnabled {
|
||||||
timer = nil
|
delegate?.buttonDidEndPress()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Tap and LongPress gesture recognizers
|
|
||||||
|
|
||||||
fileprivate func createGestureRecognizers() {
|
|
||||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(SwiftyCamButton.Tap))
|
|
||||||
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(SwiftyCamButton.LongPress))
|
|
||||||
self.addGestureRecognizer(tapGesture)
|
|
||||||
self.addGestureRecognizer(longGesture)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,22 +115,10 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
|
|
||||||
public weak var cameraDelegate: SwiftyCamViewControllerDelegate?
|
public weak var cameraDelegate: SwiftyCamViewControllerDelegate?
|
||||||
|
|
||||||
/// Maxiumum video duration if SwiftyCamButton is used
|
|
||||||
|
|
||||||
public var maximumVideoDuration : Double = 0.0
|
|
||||||
|
|
||||||
/// Video capture quality
|
/// Video capture quality
|
||||||
|
|
||||||
public var videoQuality : VideoQuality = .high
|
public var videoQuality : VideoQuality = .high
|
||||||
|
|
||||||
/// Sets whether flash is enabled for photo and video capture
|
|
||||||
@available(*, deprecated, message: "use flashMode .on or .off") //use flashMode
|
|
||||||
public var flashEnabled: Bool = false {
|
|
||||||
didSet{
|
|
||||||
self.flashMode = self.flashEnabled ? .on : .off
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flash Mode
|
// Flash Mode
|
||||||
public var flashMode:FlashMode = .off
|
public var flashMode:FlashMode = .off
|
||||||
|
|
||||||
|
|
@ -172,7 +160,7 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
|
|
||||||
public var defaultCamera = CameraSelection.rear
|
public var defaultCamera = CameraSelection.rear
|
||||||
|
|
||||||
/// Sets wether the taken photo or video should be oriented according to the device orientation
|
/// Sets wether the taken video should be oriented according to the device orientation
|
||||||
|
|
||||||
public var shouldUseDeviceOrientation = false {
|
public var shouldUseDeviceOrientation = false {
|
||||||
didSet {
|
didSet {
|
||||||
|
|
@ -259,10 +247,6 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
|
|
||||||
fileprivate var movieFileOutput : AVCaptureMovieFileOutput?
|
fileprivate var movieFileOutput : AVCaptureMovieFileOutput?
|
||||||
|
|
||||||
/// Photo File Output variable
|
|
||||||
|
|
||||||
fileprivate var photoFileOutput : AVCaptureStillImageOutput?
|
|
||||||
|
|
||||||
/// Video Device variable
|
/// Video Device variable
|
||||||
|
|
||||||
fileprivate var videoDevice : AVCaptureDevice?
|
fileprivate var videoDevice : AVCaptureDevice?
|
||||||
|
|
@ -477,31 +461,6 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Capture photo from current session
|
|
||||||
|
|
||||||
UIImage will be returned with the SwiftyCamViewControllerDelegate function SwiftyCamDidTakePhoto(photo:)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
public func takePhoto() {
|
|
||||||
|
|
||||||
guard let device = videoDevice else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if device.hasFlash == true && flashMode != .off /* TODO: Add Support for Retina Flash and add front flash */ {
|
|
||||||
changeFlashSettings(device: device, mode: flashMode)
|
|
||||||
capturePhotoAsyncronously(completionHandler: { (_) in })
|
|
||||||
}else{
|
|
||||||
if device.isFlashActive == true {
|
|
||||||
changeFlashSettings(device: device, mode: flashMode)
|
|
||||||
}
|
|
||||||
capturePhotoAsyncronously(completionHandler: { (_) in })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
Begin recording video of current session
|
Begin recording video of current session
|
||||||
|
|
||||||
SwiftyCamViewControllerDelegate function SwiftyCamDidBeginRecordingVideo() will be called
|
SwiftyCamViewControllerDelegate function SwiftyCamDidBeginRecordingVideo() will be called
|
||||||
|
|
@ -662,7 +621,6 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
addVideoInput()
|
addVideoInput()
|
||||||
addAudioInput()
|
addAudioInput()
|
||||||
configureVideoOutput()
|
configureVideoOutput()
|
||||||
configurePhotoOutput()
|
|
||||||
|
|
||||||
session.commitConfiguration()
|
session.commitConfiguration()
|
||||||
}
|
}
|
||||||
|
|
@ -790,12 +748,10 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
connection.preferredVideoStabilizationMode = .auto
|
connection.preferredVideoStabilizationMode = .auto
|
||||||
}
|
}
|
||||||
|
|
||||||
if #available(iOS 11.0, *) {
|
if let videoCodecType = videoCodecType {
|
||||||
if let videoCodecType = videoCodecType {
|
if movieFileOutput.availableVideoCodecTypes.contains(videoCodecType) == true {
|
||||||
if movieFileOutput.availableVideoCodecTypes.contains(videoCodecType) == true {
|
// Use the H.264 codec to encode the video.
|
||||||
// Use the H.264 codec to encode the video.
|
movieFileOutput.setOutputSettings([AVVideoCodecKey: videoCodecType], for: connection)
|
||||||
movieFileOutput.setOutputSettings([AVVideoCodecKey: videoCodecType], for: connection)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -803,67 +759,6 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure Photo Output
|
|
||||||
|
|
||||||
fileprivate func configurePhotoOutput() {
|
|
||||||
let photoFileOutput = AVCaptureStillImageOutput()
|
|
||||||
|
|
||||||
if self.session.canAddOutput(photoFileOutput) {
|
|
||||||
photoFileOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
|
|
||||||
self.session.addOutput(photoFileOutput)
|
|
||||||
self.photoFileOutput = photoFileOutput
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns a UIImage from Image Data.
|
|
||||||
|
|
||||||
- Parameter imageData: Image Data returned from capturing photo from the capture session.
|
|
||||||
|
|
||||||
- Returns: UIImage from the image data, adjusted for proper orientation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fileprivate func processPhoto(_ imageData: Data) -> UIImage {
|
|
||||||
let dataProvider = CGDataProvider(data: imageData as CFData)
|
|
||||||
let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)
|
|
||||||
|
|
||||||
// Set proper orientation for photo
|
|
||||||
// If camera is currently set to front camera, flip image
|
|
||||||
|
|
||||||
let image = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: self.orientation.getImageOrientation(forCamera: self.currentCamera))
|
|
||||||
|
|
||||||
return image
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate func capturePhotoAsyncronously(completionHandler: @escaping(Bool) -> ()) {
|
|
||||||
|
|
||||||
guard sessionRunning == true else {
|
|
||||||
print("[SwiftyCam]: Cannot take photo. Capture session is not running")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if let videoConnection = photoFileOutput?.connection(with: AVMediaType.video) {
|
|
||||||
|
|
||||||
photoFileOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: {(sampleBuffer, error) in
|
|
||||||
if (sampleBuffer != nil) {
|
|
||||||
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer!)
|
|
||||||
let image = self.processPhoto(imageData!)
|
|
||||||
|
|
||||||
// Call delegate and return new image
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.cameraDelegate?.swiftyCam(self, didTake: image)
|
|
||||||
}
|
|
||||||
completionHandler(true)
|
|
||||||
} else {
|
|
||||||
completionHandler(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
completionHandler(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handle Denied App Privacy Settings
|
/// Handle Denied App Privacy Settings
|
||||||
|
|
||||||
fileprivate func promptToAppSettings() {
|
fileprivate func promptToAppSettings() {
|
||||||
|
|
@ -874,13 +769,7 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
|
let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
|
||||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Settings", comment: "Alert button to open Settings"), style: .default, handler: { action in
|
alertController.addAction(UIAlertAction(title: NSLocalizedString("Settings", comment: "Alert button to open Settings"), style: .default, handler: { action in
|
||||||
if #available(iOS 10.0, *) {
|
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
|
||||||
UIApplication.shared.openURL(URL(string: UIApplication.openSettingsURLString)!)
|
|
||||||
} else {
|
|
||||||
if let appSettings = URL(string: UIApplication.openSettingsURLString) {
|
|
||||||
UIApplication.shared.openURL(appSettings)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
}))
|
||||||
self.present(alertController, animated: true, completion: nil)
|
self.present(alertController, animated: true, completion: nil)
|
||||||
})
|
})
|
||||||
|
|
@ -905,52 +794,15 @@ open class SwiftyCamViewController: UIViewController {
|
||||||
case .resolution1920x1080: return AVCaptureSession.Preset.hd1920x1080.rawValue
|
case .resolution1920x1080: return AVCaptureSession.Preset.hd1920x1080.rawValue
|
||||||
case .iframe960x540: return AVCaptureSession.Preset.iFrame960x540.rawValue
|
case .iframe960x540: return AVCaptureSession.Preset.iFrame960x540.rawValue
|
||||||
case .iframe1280x720: return AVCaptureSession.Preset.iFrame1280x720.rawValue
|
case .iframe1280x720: return AVCaptureSession.Preset.iFrame1280x720.rawValue
|
||||||
case .resolution3840x2160:
|
case .resolution3840x2160: return AVCaptureSession.Preset.hd4K3840x2160.rawValue
|
||||||
if #available(iOS 9.0, *) {
|
|
||||||
return AVCaptureSession.Preset.hd4K3840x2160.rawValue
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print("[SwiftyCam]: Resolution 3840x2160 not supported")
|
|
||||||
return AVCaptureSession.Preset.high.rawValue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get Devices
|
/// Get Devices
|
||||||
|
|
||||||
fileprivate class func deviceWithMediaType(_ mediaType: String, preferringPosition position: AVCaptureDevice.Position) -> AVCaptureDevice? {
|
fileprivate class func deviceWithMediaType(_ mediaType: String, preferringPosition position: AVCaptureDevice.Position) -> AVCaptureDevice? {
|
||||||
if #available(iOS 10.0, *) {
|
let avDevice = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: AVMediaType(rawValue: mediaType), position: position)
|
||||||
let avDevice = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: AVMediaType(rawValue: mediaType), position: position)
|
return avDevice
|
||||||
return avDevice
|
|
||||||
} else {
|
|
||||||
// Fallback on earlier versions
|
|
||||||
let avDevice = AVCaptureDevice.devices(for: AVMediaType(rawValue: mediaType))
|
|
||||||
var avDeviceNum = 0
|
|
||||||
for device in avDevice {
|
|
||||||
print("deviceWithMediaType Position: \(device.position.rawValue)")
|
|
||||||
if device.position == position {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
avDeviceNum += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return avDevice[avDeviceNum]
|
|
||||||
}
|
|
||||||
|
|
||||||
//return AVCaptureDevice.devices(for: AVMediaType(rawValue: mediaType), position: position).first
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enable or disable flash for photo
|
|
||||||
|
|
||||||
fileprivate func changeFlashSettings(device: AVCaptureDevice, mode: FlashMode) {
|
|
||||||
do {
|
|
||||||
try device.lockForConfiguration()
|
|
||||||
device.flashMode = mode.AVFlashMode
|
|
||||||
device.unlockForConfiguration()
|
|
||||||
} catch {
|
|
||||||
print("[SwiftyCam]: \(error)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable flash
|
/// Enable flash
|
||||||
|
|
@ -1012,14 +864,7 @@ fileprivate func changeFlashSettings(device: AVCaptureDevice, mode: FlashMode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
do{
|
do{
|
||||||
if #available(iOS 10.0, *) {
|
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
||||||
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
|
||||||
} else {
|
|
||||||
let options: [AVAudioSession.CategoryOptions] = [.mixWithOthers, .allowBluetooth]
|
|
||||||
let category = AVAudioSession.Category.playAndRecord
|
|
||||||
let selector = NSSelectorFromString("setCategory:withOptions:error:")
|
|
||||||
AVAudioSession.sharedInstance().perform(selector, with: category, with: options)
|
|
||||||
}
|
|
||||||
try AVAudioSession.sharedInstance().setActive(true)
|
try AVAudioSession.sharedInstance().setActive(true)
|
||||||
session.automaticallyConfiguresApplicationAudioSession = false
|
session.automaticallyConfiguresApplicationAudioSession = false
|
||||||
}
|
}
|
||||||
|
|
@ -1050,34 +895,15 @@ fileprivate func changeFlashSettings(device: AVCaptureDevice, mode: FlashMode) {
|
||||||
|
|
||||||
extension SwiftyCamViewController : SwiftyCamButtonDelegate {
|
extension SwiftyCamViewController : SwiftyCamButtonDelegate {
|
||||||
|
|
||||||
/// Sets the maximum duration of the SwiftyCamButton
|
/// Begin video when the button is pressed down
|
||||||
|
|
||||||
public func setMaxiumVideoDuration() -> Double {
|
public func buttonDidBeginPress() {
|
||||||
return maximumVideoDuration
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set UITapGesture to take photo
|
|
||||||
|
|
||||||
public func buttonWasTapped() {
|
|
||||||
takePhoto()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set UILongPressGesture start to begin video
|
|
||||||
|
|
||||||
public func buttonDidBeginLongPress() {
|
|
||||||
startVideoRecording()
|
startVideoRecording()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set UILongPressGesture begin to begin end video
|
/// End video when the button is released
|
||||||
|
|
||||||
|
public func buttonDidEndPress() {
|
||||||
public func buttonDidEndLongPress() {
|
|
||||||
stopVideoRecording()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called if maximum duration is reached
|
|
||||||
|
|
||||||
public func longPressDidReachMaximumDuration() {
|
|
||||||
stopVideoRecording()
|
stopVideoRecording()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1117,13 +943,21 @@ extension SwiftyCamViewController {
|
||||||
|
|
||||||
/// Handle pinch gesture
|
/// Handle pinch gesture
|
||||||
|
|
||||||
|
private var firstCaptureDevice: AVCaptureDevice? {
|
||||||
|
AVCaptureDevice.DiscoverySession(
|
||||||
|
deviceTypes: [.builtInDualCamera, .builtInWideAngleCamera],
|
||||||
|
mediaType: .video,
|
||||||
|
position: .unspecified
|
||||||
|
).devices.first
|
||||||
|
}
|
||||||
|
|
||||||
@objc fileprivate func zoomGesture(pinch: UIPinchGestureRecognizer) {
|
@objc fileprivate func zoomGesture(pinch: UIPinchGestureRecognizer) {
|
||||||
guard pinchToZoom == true && self.currentCamera == .rear else {
|
guard pinchToZoom == true && self.currentCamera == .rear else {
|
||||||
//ignore pinch
|
//ignore pinch
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
let captureDevice = AVCaptureDevice.devices().first
|
let captureDevice = firstCaptureDevice
|
||||||
try captureDevice?.lockForConfiguration()
|
try captureDevice?.lockForConfiguration()
|
||||||
|
|
||||||
zoomScale = min(maxZoomScale, max(1.0, min(beginZoomScale * pinch.scale, captureDevice!.activeFormat.videoMaxZoomFactor)))
|
zoomScale = min(maxZoomScale, max(1.0, min(beginZoomScale * pinch.scale, captureDevice!.activeFormat.videoMaxZoomFactor)))
|
||||||
|
|
@ -1198,7 +1032,7 @@ extension SwiftyCamViewController {
|
||||||
let translationDifference = currentTranslation - previousPanTranslation
|
let translationDifference = currentTranslation - previousPanTranslation
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let captureDevice = AVCaptureDevice.devices().first
|
let captureDevice = firstCaptureDevice
|
||||||
try captureDevice?.lockForConfiguration()
|
try captureDevice?.lockForConfiguration()
|
||||||
|
|
||||||
let currentZoom = captureDevice?.videoZoomFactor ?? 0.0
|
let currentZoom = captureDevice?.videoZoomFactor ?? 0.0
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,12 @@ import AVFoundation
|
||||||
|
|
||||||
/// Delegate for SwiftyCamViewController
|
/// Delegate for SwiftyCamViewController
|
||||||
|
|
||||||
public protocol SwiftyCamViewControllerDelegate: class {
|
public protocol SwiftyCamViewControllerDelegate: AnyObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
SwiftyCamViewControllerDelegate function called when when SwiftyCamViewController session did start running.
|
SwiftyCamViewControllerDelegate function called when when SwiftyCamViewController session did start running.
|
||||||
Photos and video capture will be enabled.
|
Video capture will be enabled.
|
||||||
|
|
||||||
- Parameter swiftyCam: Current SwiftyCamViewController
|
- Parameter swiftyCam: Current SwiftyCamViewController
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -34,22 +34,13 @@ public protocol SwiftyCamViewControllerDelegate: class {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
SwiftyCamViewControllerDelegate function called when when SwiftyCamViewController session did stops running.
|
SwiftyCamViewControllerDelegate function called when when SwiftyCamViewController session did stops running.
|
||||||
Photos and video capture will be disabled.
|
Video capture will be disabled.
|
||||||
|
|
||||||
- Parameter swiftyCam: Current SwiftyCamViewController
|
- Parameter swiftyCam: Current SwiftyCamViewController
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func swiftyCamSessionDidStopRunning(_ swiftyCam: SwiftyCamViewController)
|
func swiftyCamSessionDidStopRunning(_ swiftyCam: SwiftyCamViewController)
|
||||||
|
|
||||||
/**
|
|
||||||
SwiftyCamViewControllerDelegate function called when the takePhoto() function is called.
|
|
||||||
|
|
||||||
- Parameter swiftyCam: Current SwiftyCamViewController session
|
|
||||||
- Parameter photo: UIImage captured from the current session
|
|
||||||
*/
|
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didTake photo: UIImage)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
SwiftyCamViewControllerDelegate function called when SwiftyCamViewController begins recording video.
|
SwiftyCamViewControllerDelegate function called when SwiftyCamViewController begins recording video.
|
||||||
|
|
||||||
|
|
@ -142,21 +133,14 @@ public extension SwiftyCamViewControllerDelegate {
|
||||||
// Optional
|
// Optional
|
||||||
}
|
}
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didTake photo: UIImage) {
|
|
||||||
// Optional
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
|
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
|
||||||
// Optional
|
// Optional
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
|
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
|
||||||
// Optional
|
// Optional
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishProcessVideoAt url: URL) {
|
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishProcessVideoAt url: URL) {
|
||||||
// Optional
|
// Optional
|
||||||
}
|
}
|
||||||
|
|
@ -168,13 +152,11 @@ public extension SwiftyCamViewControllerDelegate {
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didSwitchCameras camera: SwiftyCamViewController.CameraSelection) {
|
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didSwitchCameras camera: SwiftyCamViewController.CameraSelection) {
|
||||||
// Optional
|
// Optional
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFocusAtPoint point: CGPoint) {
|
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFocusAtPoint point: CGPoint) {
|
||||||
// Optional
|
// Optional
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didChangeZoomLevel zoom: CGFloat) {
|
func swiftyCam(_ swiftyCam: SwiftyCamViewController, didChangeZoomLevel zoom: CGFloat) {
|
||||||
// Optional
|
// Optional
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue