6

I have created a sound player in swift with AVFoundation. I am trying to start the next song in array when the playing song is finished. I was trying to implement this code

if (audioPlayer.currentTime >= audioPlayer.duration){
    var recentSong = songPlaylist[selectedSongNumber + 1]
    audioPlayer = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath:
            NSBundle.mainBundle().pathForResource(recentSong, ofType: "mp3")!), error: nil)
    audioPlayer.play()
}

but I am not being able to implement this code (I do not know where to implement it).Here is my complete code

import UIKit
import AVFoundation
import AVKit

public var audioPlayer = AVPlayer()
public var selectedSongNumber = Int()
public var songPlaylist:[String] = ["song1", "song2"]
public var recentSong = "song1"
let playImage = UIImage(named: "Play.png") as UIImage!
let pauseImage = UIImage(named: "Pause.png") as UIImage!

class FirstViewController: UIViewController {

@IBOutlet weak var musicSlider: UISlider!

@IBOutlet weak var PlayPause: UIButton!

var audioPlayer = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath:
    NSBundle.mainBundle().pathForResource(recentSong, ofType: "mp3")!), error: nil)

override func viewDidLoad() {
    super.viewDidLoad()

    musicSlider.maximumValue = Float(audioPlayer.duration)

    var timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateMusicSlider"), userInfo: nil, repeats: true)


    if (audioPlayer.currentTime >= audioPlayer.duration){

        var recentSong = songPlaylist[selectedSongNumber + 1]

        audioPlayer = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath:
            NSBundle.mainBundle().pathForResource(recentSong, ofType: "mp3")!), error: nil)

        audioPlayer.play()

        }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}
@IBAction func PlayPauseButton(sender: AnyObject) {

    if (audioPlayer.playing == false){
        audioPlayer.play()
        PlayPause.setImage(pauseImage, forState: .Normal)
    }else{
        audioPlayer.pause()
        PlayPause.setImage(playImage, forState: .Normal)
    }
}

@IBAction func StopButton(sender: AnyObject) {
    audioPlayer.stop()
    audioPlayer.currentTime = 0
    PlayPause.setImage(playImage, forState: .Normal)
}

@IBAction func musicSliderAction(sender: UISlider) {
    audioPlayer.stop()
    audioPlayer.currentTime = NSTimeInterval(musicSlider.value)
    audioPlayer.play()

}

func updateMusicSlider(){

    musicSlider.value = Float(audioPlayer.currentTime)

}

}
WhiteLine
  • 1,919
  • 2
  • 25
  • 53
Ilir V. Gruda
  • 1,562
  • 5
  • 17
  • 23

3 Answers3

10

I am updating my code with something different:

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioPlayerDelegate {

    var counter = 0
    var song = ["1","2","3"]
    var player = AVAudioPlayer()

    @IBOutlet weak var musicSlider: UISlider!

    override func viewDidLoad() {
        super.viewDidLoad()
        musicSlider.value = 0.0
    }

    func updateMusicSlider(){

        musicSlider.value = Float(player.currentTime)
    }

    @IBAction func playSong(sender: AnyObject) {

        music()
    }
    @IBAction func sliderAction(sender: AnyObject) {

        player.stop()
        player.currentTime = NSTimeInterval(musicSlider.value)
        player.play()
    }

    func music(){

        var audioPath = NSBundle.mainBundle().pathForResource("\(song[counter])", ofType: "mp3")!
        var error : NSError? = nil
        player = AVAudioPlayer(contentsOfURL: NSURL(string: audioPath), error: &error)
        musicSlider.maximumValue = Float(player.duration)
        var timer = NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: Selector("updateMusicSlider"), userInfo: nil, repeats: true)
        player.delegate = self
        if error == nil {
            player.delegate = self
            player.prepareToPlay()
            player.play()
        }
    }

    func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool)
    {
        println("Called")
        if flag {
            counter++
        }

        if ((counter + 1) == song.count) {
            counter = 0
        }

        music()
    }

}

You can do it this way.

Hope It will help and HERE is sample project for more Info.

Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
  • actually know that I was doing some more tests I just realised that the next song is starting only one time after the first song ends, but when the second song ends third song is not starting to play, and even if I go back in the first song from the second than second song is not starting. I think the problem may be that the `player: AVAudioPlayer` is not being updated, any suggestion ? – Ilir V. Gruda Jun 06 '15 at 11:10
1

You need to implement AVAudioPlayerDelegate Protocol's method:

optional func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer!, successfully flag: Bool)

Documentation link

Play your next music item here.

But I will not recommend, since AVAudioPlayer can only play one item at a time. You need to instantiate again with another music item after completion. I will suggest you to use AVQueuePlayer. Detaled answer has been given here. Hope it helps!

Community
  • 1
  • 1
NightFury
  • 13,436
  • 6
  • 71
  • 120
0

I created a sound player in swift with AVFoundation. I used progressView to time the song and then when it hits 0.98743 it will update to the next song automatically this is the Github link: https://github.com/ryan-wlr/MusicPlayerIOS

func updateProgressView() {
    if (progressView.progress > a.advanced(by: 0.98743)) {
        audioPlayerDidFinishPlayeing()
    }

    if audioPlayer.isPlaying {
        let progress = Float(audioPlayer.currentTime/audioPlayer.duration)
        progressView.setProgress(progress, animated: true)
    }
}
Sethmr
  • 3,046
  • 1
  • 24
  • 42