0

Im trying to set a slider to the current value of an audio file which is playing. But I'm getting problems when setting the values for the slider.

when i use a timer from ViewDidLoad:

self.timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(PlayerViewController.audioSliderUpdate), userInfo: nil, repeats: true)

which calls my function:

func audioSliderUpdate() {

 var currentTime : CMTime = (self.audioPlayerItem?.currentTime())!
 var seconds : Float64 = CMTimeGetSeconds(currentTime)
 var time : Float = Float(seconds)

    self.audioSlider.value = time

}

The audio track starts skipping and the slider is jumping about and it returns this to the console:

[aqme] 255: AQDefaultDevice (173): skipping input stream 0 0 0x0

and when i try set the max value with this code:

   let duration : CMTime = (self.audioPlayerItem?.duration)!
   let seconds : Float64 = CMTimeGetSeconds(duration)
   let maxTime : Float = Float(seconds)

   self.audioSlider.valueMaximum = maxTime

i get this error:

<Error>: Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem.
Jan 20 07:24:23  ParseStarterProject-Swift[2441] <Error>: If you want to see the backtrace, please set CG_NUMERICS_SHOW_BACKTRACE environmental variable.

I've read all over SO and they all have simple solutions like

let floatTime = Float(player.currentTime)

which don't work. as you cant convert CMT directly to float in swift 3????

So my question is how do i set the values for the slider?

this is the entire class to shed light if my explanation was unclear:

import UIKit
import Parse
import AVFoundation
import AVKit


class PlayerViewController: UIViewController, AVAudioPlayerDelegate {

@IBOutlet var audioSlider: MTCircularSlider!
// passed objectID from PackViewController
var selectedAudio: String!

var audioPlayer: AVPlayer?
var audioPlayerItem: AVPlayerItem?

fileprivate var timer: Timer?
fileprivate var direction: Float = 0.01


// query parse to get the file and stream it
func getAudio() {

    let query = PFQuery(className: "Part")
        query.whereKey("objectId", equalTo: selectedAudio)
        query.getFirstObjectInBackground { (object, error) in

            if error != nil || object == nil {

                print("The getFirstObject request failed.")

            } else {

                print("There is an object now get the Audio. ")

                if let audioFileURL = (object?.object(forKey: "partAudio") as! PFFile).url {

                        // create an item for use by notification center
                        self.audioPlayerItem = AVPlayerItem(url: NSURL(string: audioFileURL) as! URL)

                            self.audioPlayer = AVPlayer(playerItem: self.audioPlayerItem)

                        self.audioPlayer?.play()


                    var duration : CMTime = (self.audioPlayerItem?.duration)!
                    var seconds : Float64 = CMTimeGetSeconds(duration)
                    var maxTime : Float = Float(seconds)

                    self.audioSlider.valueMaximum = maxTime


                    self.timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(PlayerViewController.audioSliderUpdate), userInfo: nil, repeats: true)
                }

            }
        }
}


@IBOutlet var playerButton: UIButton!


func playerButtonTapped() {

    // if the player is not playing
    if audioPlayer?.rate == 0 {

        audioPlayer?.play()
            self.playerButton.setImage(UIImage(named: "play"), for: UIControlState.normal)

    } else {

        audioPlayer?.pause()
            self.playerButton.setImage(UIImage(named: "pause"), for: UIControlState.normal)

    }

}

func finishedPlaying (myNotification: NSNotification) {

    self.playerButton.setImage(UIImage(named: "play"), for: UIControlState.normal)

    let stoppedPlayerItem: AVPlayerItem = myNotification.object as! AVPlayerItem

        //create a CMTime for zero seconds so we can go back to the beginning
        let seconds : Int64 = 0
            let preferredTimeScale : Int32 = 1
                let seekTime : CMTime = CMTimeMake(seconds, preferredTimeScale)

        stoppedPlayerItem.seek(to: seekTime)
}


override func viewDidLoad() {
    super.viewDidLoad()

    self.playerButton.addTarget(self, action: #selector(PlayerViewController.playerButtonTapped), for: UIControlEvents.touchUpInside)

    getAudio()

}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(audioPlayerItem as Any, selector: #selector(PlayerViewController.finishedPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: audioPlayer)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // remove the observer when leaving page
    NotificationCenter.default.removeObserver(audioPlayer?.currentItem! as Any)
}

@IBAction func audioSliderActioned(_ sender: Any) {

    audioPlayer?.pause()
    //audioPlayer.currentTime() = TimeInterval(audioSlider.value)
    //audioPlayer.prepareToPlay()
    audioPlayer?.play()

}

func audioSliderUpdate() {



    var currentTime : CMTime = (self.audioPlayerItem?.currentTime())!
    var seconds : Float64 = CMTimeGetSeconds(currentTime)
    var time : Float = Float(seconds)

    self.audioSlider.value = time

}

}
Pippo
  • 1,439
  • 1
  • 18
  • 35

0 Answers0