OpenTok Session Volume Change Doesn't work with MPVolumeView - ios

Hi I've been working on using Open Tok For a streaming session
I used MPVolumeView to vary system Sound.
Issue: MPVolumeView does work changing system Volume but that doesn't affect my OTSession Volume
Expected: I want to change "outputVolume" of AVAudioSession running with OpenTok
Code:
func startObservingVolumeChanges() {
avAudioSession.addObserver(self, forKeyPath: Observation.VolumeKey, options: [.initial, .new], context: &Observation.Context)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &Observation.Context {
if keyPath == Observation.VolumeKey, let volume = (change?[NSKeyValueChangeKey.newKey] as? NSNumber)?.floatValue {
print("Volume: \(volume)")
}
} else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
func stopObservingVolumeChanges() {
avAudioSession.removeObserver(self, forKeyPath: Observation.VolumeKey, context: &Observation.Context)
}
As soon as I change volume using iOS Volume buttons "Volume does get print from 0 to 1 range"
when I change value using Slider "Volume does get print from 0 to 1 range" but doesn't lower the sound of Session
Please help.

Discussed with OpenTok Developers. This is not supported attaching screenshot for same,

Related

KVO AVPlayer.status in Swift

I need to observe AVPlayer.status change.
I have an AVPlayer instance and a context variable
private var lastPlayer : AVPlayer?
private var playerStatusContext = 0
After I've set up the AVPlayer instance I add an observer like so:
// KVO status property
self.lastPlayer!.addObserver(self, forKeyPath: "status", options: [.new, .initial], context: &playerStatusContext)
Then I've overridden observeValue function like so:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
let status : AVPlayerStatus? = change?[.newKey] as? AVPlayerStatus
if(status != nil && context == &playerStatusContext)
{
// DO MY STUFF
}
}
The problem is that change is either 0 key/value dictionary or some (whatever that means) and my local status constant is always nil, hense I can't do my stuff.
Maybe I am converting change to AVPlayerStatus wrongly? Please help. Thanks.
Well, it seems like cast like this
let status : AVPlayerStatus? = change?[.newKey] as? AVPlayerStatus
does not work. The app crashed when tried checking change for nil and then force unwrap it. Using raw values helped:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
// Check status
if keyPath == "status" && context == &playerStatusContext && change != nil
{
let status = change![.newKey] as! Int
// Status is not unknown
if(status != AVPlayerStatus.unknown.rawValue)
{
// DO STUFF!!!
}
}
}
I am not sure this is the best way however.

AVPlayer on selected rate only once

I've got an issue with AVPlayer. The case is: I've got one function, that sets the rate of AVPlayer
func applyEffect(effectNumber : Int) {
switch effectNumber {
case 0:
self.AvPlayer.setRate(Float(1.0), time: kCMTimeInvalid, atHostTime: kCMTimeInvalid)
case 1:
self.AvPlayer.setRate(Float(1.5), time: kCMTimeInvalid, atHostTime: kCMTimeInvalid)
case 2:
self.AvPlayer.setRate(Float(0.5), time: kCMTimeInvalid, atHostTime: kCMTimeInvalid)
default:
self.AvPlayer.setRate(Float(1.0), time: kCMTimeInvalid, atHostTime: kCMTimeInvalid)
}
}
For every response I download audio file into AVPlayerItem and save them as array. I've got an observer for item which calls applyEffect function if AVPlayerItem.status is changed, otherwise it applies effect immediately:
if AVCurrentItem.status != AVPlayerItemStatus.readyToPlay {
AVCurrentItem.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil)
pushMessageLoading()
} else {
self.applyEffect(effectNumber: currentEffect)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "status" {
popMessageLoading()
self.applyEffect(effectNumber: currentEffect)
AVCurrentItem.removeObserver(self, forKeyPath: "status")
}
}
The AVPlayer property "automaticallyWaitsToMinimizeStalling" is set to false during the initialisation. So, first time audio plays on a requested rate, but all times after - on rate like 1.0. What's the problem?
The root of evil is simple: I've used AVPlayer.play which equals to AVPlayer.rate = 1.0, instead of this you need to use AVPlayer.rate = desired value

Is it possible to use KVO to track changes to the `MKMapView.camera.heading` property?

I am trying to track changes to the map orientation using the camera heading property.
// Register for notifications of changes to camera
if let camera = self.mapView?.camera {
self.camera = camera
camera.addObserver(self, forKeyPath: "heading", options: NSKeyValueObservingOptions.new, context: &MapViewController.myContext)
}
...
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &MapViewController.myContext {
if keyPath == "heading" {
if let heading = change?[NSKeyValueChangeKey.newKey] as? CLLocationDirection {
self.heading = heading
}
}
} else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
The camera property mode is copy so you are not observing the current camera instance just one that was copied when you called the getter. You need to observe key path of #"camera.heading" or #"camera" on the map view and hope that a new camera object is set internally when the heading changes.

Detect when AvPlayer is stopped

I'm using the AVPlayer class to read streams.
I have to monitor playback.
Here is my question : Is it possible to detect when the player is stopped by the user ?
I looked at MPMoviePlayerController. If the user stopped the video, this controller sends a notification : MPMovieFinishReasonUserExited. Is there an equivalent ?
You can monitor rate property by adding observer on the player for key rate.
A value of 0.0 means pauses the video, while a value of 1.0 play at the natural rate of the current item.
Apple documentation and this topic.
Hope this helps.
here's the swift 3 code for #Thlbaut's answer
self.avPlayer?.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions(rawValue: 0), context: nil)
then
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "rate" {
if let playRate = self.avPlayer?.rate {
if playRate == 0.0 {
print("playback paused")
} else {
print("playback started")
}
}
}
}

Detect when camera is auto-focusing

I am working on video application. I want to discard the video frames when camera is autofocusing. During autofocus image captured become blurred and image processing for that frame become bad but once autofocus is done, image processing become excellent. Any body give me solution?
adjustingFocus property.
Indicates whether the device is currently adjusting its focus setting. (read-only)
*Notes: You can observe changes to the value of this property using Key-value observing.
iOS 4.0 and later
https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVCaptureDevice_Class/Reference/Reference.html#//apple_ref/occ/instp/AVCaptureDevice/adjustingFocus
Following is a sample code in Swift 3.x.
First a observer should be added to the selected capture device at camera initialization.
captureDevice.addObserver(self, forKeyPath: "adjustingFocus", options: [.new], context: nil)
Then observeValue method is overridden. By accessing the optional value returned by the method, autoFocussing frames can be identified.
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let key = keyPath, let changes = change else {
return
}
if key == "adjustingFocus" {
let changedValue = changes[.newKey]
if (changedValue! as! Bool){
// camera is auto-focussing
}else{
// camera is not auto-focussing
}
}
}
Example on Swift 4+
class ViewController: UIViewController, AVCapturePhotoCaptureDelegate {
//#objc var captureDevice: AVCaptureDevice?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.addObservers()
}
func addObservers() {
self.addObserver(self, forKeyPath: "captureDevice.adjustingFocus", options: .new, context: nil)
}
func removeObservers() {
self.removeObserver(self, forKeyPath: "captureDevice.adjustingFocus")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "captureDevice.adjustingFocus" {
print("============== adjustingFocus: \(self.captureDevice?.lensPosition)")
}
} //End of class
Observing adjustingFocus is not working for me. It's always no. And I find this.
Note that when traditional contrast detect auto-focus is in use, the AVCaptureDevice adjustingFocus property flips to YES when a focus is underway, and flips back to NO when it is done. When phase detect autofocus is in use, the adjustingFocus property does not flip to YES, as the phase detect method tends to focus more frequently, but in small, sometimes imperceptible amounts. You can observe the AVCaptureDevice lensPosition property to see lens movements that are driven by phase detect AF.
from Apple
I have not try it yet, I will try and update later.
Edit. I have try it, and confirm this's right.

Resources