Turn on light/torch with front camera - ios

I know how to turn on/off the flash light from the back camera. I know how to switch front/back camera. But I don't know how to turn on/off the flash light independently from the active camera.
What I mean: if the active camera is the front one, when I turn on the flash light, it freezes. And when I turn it off, it unfreezes.
My code so far:
var back_cam:AVCaptureDevice?
for device in devices{
if (device as AnyObject).hasMediaType(AVMediaTypeVideo) && (device as AnyObject).position == .back{
back_cam=device as? AVCaptureDevice
}
}
guard let cam=back_cam else {
print("no back cam?")
return
}
if cam.hasTorch{
do{
try cam.lockForConfiguration()
if cam.torchMode == .on{
cam.torchMode = .off
}else{
do{
try cam.setTorchModeOnWithLevel(1)
}catch{
print(error)
}
}
cam.unlockForConfiguration()
}catch{
print(error)
}
}
}
EDIT
In case I'm not clear, I'd like to keep the light on, regardless of wether the active camera is the back one or the front one.

You need to check torch mode is supported for the device or not before you turn on/off.
As per Apple documentation for
var torchMode: AVCaptureTorchMode { get set }
Before setting the value of this property, call the
isTorchModeSupported(_:) method to make sure the device supports the
desired mode. Setting the device to an unsupported torch mode results
in the raising of an exception.
Also when you switch to front camera, the default behaviour is torch mode off. Compare it with default camera app from iPhone/iPad.

Related

How can I switch between 11 pro cameras using AVFoundation in Xcode

I've just started out learning Swift in Xcode and am creating a simple camera App to get up and running. I have a button that switches between the front and back facing cameras working but want to add the option to also switch between the Tele and the Ultra Wide lens on the iPhone 11 Pro.
I have created the functions to run a new CaptureSession for each lens (if detected) but was just wondering how I can call these functions to UIbutton function
The thing that's got me scratching my head is the if statement used to switch between the front and back camera says if input.device.position == .back {
This only specificities if it's front or back, not the lens itself. What would be an efficient way to make the button then Change from the front to wide, the Tele, the Ultra Wide and back to the front each time the button is pressed?
Apologies for any misuse of terminology, I'm very new to coding in Swift. Thank you!
{
guard let CurrentCameraInput: AVCaptureInput = CaptureSession?.inputs.first else {
return
}
if let input = CurrentCameraInput as? AVCaptureDeviceInput
{
if input.device.position == .back {
SwitchToFrontCamera() }
if input.device.position == .front {
SwitchToBackCamera()
}
}
}
Welcome!
Check you this initializer for AVCaptureDevice. You can specify the DeviceType you want to use, like .builtInUltraWideCamera or .builtInTelephotoCamera.
You can use a AVCaptureDevice.DiscoverySession to get a list of all capture devices available to your app.

AVAudioSession - How to switch between speaker and headphones output

I'm trying to mimic behaviour as in Phone app during calling. You can easily switch output sources from/to speaker or headphones.
I know I can force speaker as an output when headphones are connected by calling:
try! audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try! audioSession.overrideOutputAudioPort(.speaker)
However, when I do that, I don't see any way to detect if headphones are still connected to the device.
I initially thought outputDataSources on AVAudioSession would return all posible outputs but it always returns nil.
Is there something I'm missing
You need to change the outputDataSources, as when you overrode it,
now it contains only the .Speaker option
in the Documentation you can find the solution to this,
If your app uses the playAndRecord category, calling this method with the AVAudioSession.PortOverride.speaker option causes audio to be routed to the built-in speaker and microphone regardless of other settings. This change remains in effect only until the current route changes or you call this method again with the AVAudioSession.PortOverride.none option.
Therefore the audio is routed to the built-in speaker, This change remains in effect only untill the current route changes or you call this method again with .noneOption.
it's not possible to forcefully direct sound to headphone unless an accessory is plugged to headphone jack (which activates a physical switch to direct voice to headphone).
So when you want to switch back to headphone, this should work.
And if there is no headphone connected will switch the output device to the small speaker output on the top of the device instead of the big speaker.
let session: AVAudioSession = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
try session.overrideOutputAudioPort(AVAudioSession.PortOverride.none)
try session.setActive(true)
} catch {
print("Couldn't override output audio port")
}
Read about this AVAdioSession/OverrideOutputAudioPort Here.
You can check if headset connected adding this extension,
extension AVAudioSession {
static var isHeadphonesConnected: Bool {
return sharedInstance().isHeadphonesConnected
}
var isHeadphonesConnected: Bool {
return !currentRoute.outputs.filter { $0.isHeadphones }.isEmpty
}
}
extension AVAudioSessionPortDescription {
var isHeadphones: Bool {
return portType == AVAudioSessionPortHeadphones
}
}
And simply use this line of code
session.isHeadphonesConnected

Can use DJI SDK to replicate "Pitch Lock" feature of DJI Go app?

I'm trying to replicate the "Pitch Lock" on / off feature of the DJI Go app. How can I do this?
I'm using XCode 8.2.1, building for iOS 10.1, connecting to an Osmo Mobile with an iPhone 6s attached. The Osmo Mobile has the latest firmware (version 01.30.01.52).
Everything works so far (registerApp, connecting via bluetooth, getting handheld button presses, getting gimbal battery updates, getting gimbal updates).
Setting setGimbalWorkMode to either .freeMode or .yawFollowMode doesn't seem to have any effect. No error is returned in the completion block, but there's no effect on Gimbal operation.
The gimbal behaves as if it is in .freeMode (always moves to the exact direction handheld stick is pointing), but DJIGimbalDelegate only receives .yawFollowMode updates (which is what the pitchLock mode should do).
Setting setGimbalWorkMode to other modes results in an error (as expected with Osmo Mobile device).
Here's how I'm trying to toggle pitchLock on/off.
#IBAction func pitchLockPressed(_ sender: UIButton) {
pitchLock = !pitchLock
if let gimbal = fetchGimbal() {
var workMode : DJIGimbalWorkMode = .freeMode // .freeMode .fpvMode and .unknown return error using Osmo Mobile
if pitchLock {
workMode = .yawFollowMode
}
gimbal.setGimbalWorkMode(workMode, withCompletion: { (error) in
if (error != nil) {
print("error workMode: \(error?.localizedDescription)")
self.pitchLock = !(self.pitchLock) // back to previous
}
})
}
}
Here's the delegate, which only reports .yawFollowMode no matter what I do:
func gimbal(_ gimbal: DJIGimbal, didUpdate gimbalState: DJIGimbalState) {
// var needUpdate = false
if lastReportedWorkMode != gimbalState.workMode {
lastReportedWorkMode = gimbalState.workMode
switch lastReportedWorkMode {
case DJIGimbalWorkMode.fpvMode:
print("FPV\n")
case DJIGimbalWorkMode.freeMode:
print("Free\n")
case DJIGimbalWorkMode.yawFollowMode:
print("Yaw-follow\n")
case DJIGimbalWorkMode.unknown:
print("Unknown\n")
}
}
Anyone getting setGimbalWorkMode to actually change gimbal modes?

How to focus FRONT camera on device using iOS, swift?

it seems that front camera doesn't support focusMode.
func configureDevice() {
if let device = captureDevice {
let focusMode: AVCaptureFocusMode = .AutoFocus
if device.isFocusModeSupported(focusMode) {
device.lockForConfiguration(nil)
device.focusMode = AVCaptureFocusMode.AutoFocus
device.unlockForConfiguration()
println("configured device")
}
}
}
This code doesn't run because
if device.isFocusModeSupported(focusMode)
returns false.
But within the built-in-camera-app, front camera can focus on tap.
Is there any way implement tap-to-focus on the FRONT camera?
The front-facing camera does not support tap-to-focus on any iPhone. You can use device.focusPointOfInterestSupported property to check if you can do tap-to-focus (but you will get false, as with isFocusModeSupported())
What you are seeing is tap-for-exposure, and you can check for that with device.exposurePointOfInterestSupported. Once you know that you can use it, use device.exposurePointOfInterest to set your PoI.
All the details of each mode is explained to detail in Apple Docs
Hope it helps!

Is there any way to programmatically set the camera focus off an iOS device to infinity?

I am creating an app that locks the camera focus for video recording purposes. I want to lock the focus to infinity without having the user manually adjust the focus. Is this possible? Thanks!
Sadly, no. You can set the camera into focus-locked mode, as Artem said; put into autofocus mode (focus, then lock), or continuous autofocus mode, but you can't give the camera a specific distance to focus at.
The best I've been able to come up with (for exposure and white balance control, which are similarly limited) is to have the user point the camera at an appropriate scene (in your case, something far away) and have him/her push a lock button.
Details on the capture device API, such as it is:
https://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVCaptureDevice_Class/Reference/Reference.html
That is the way to disable focus, it locks it for all the time:
// Find a suitable capture device
AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// SETUP FOCUS MODE
if ([cameraDevice lockForConfiguration:nil]) {
[cameraDevice setFocusMode:AVCaptureFocusModeLocked];
[cameraDevice unlockForConfiguration];
}
else{
NSLog(#"error while configuring focusMode");
}
What do you mean "lock the focus to infinity"?
AVCaptureDevice has function setFocusModeLockedWithLensPosition:completionHandler:
You can use it to set 1.0 in order to achieve "infinity" distance
func focusTo(value : Float) {
if let device = captureDevice {
if(device.lockForConfiguration(nil)) {
device.setFocusModeLockedWithLensPosition(value, completionHandler: { (time) -> Void in
//
})
device.unlockForConfiguration()
}
}
Update:
According to Apple documentation 1.0 does not represent focus at infinity.

Resources