rebecca87
rebecca87

Reputation: 69

AVQueuePlayer and AVAudioPlayer called at same time

I have a screen with 3 different buttons. When Button1 is tapped an AVQueuePlayer is called. When Button2 or Button3 is tapped, an AVAudioPlayer is called.

The problem arises when Button1 is tapped (initiating the AVQueuePlayer) and then either Button2 or Button3 is tapped (initiating the AVAudioPlayer). The result is that that the audio file currently being played by the AVQueuePlayer and the audio file being played by the AVAudioPlayer play at the same time.

I`m looking for a way to either prevent Button2 or Button3 from being tapped on while the AVQueuePlayer is active, or, have the AVQueuePlayer stop playing if the user taps on either Button2 or Button3.

I found that Instead of using two Player,using only one Player will solve the problem, but I do not know how.

        var queue = AVQueuePlayer()
        var items = [AVPlayerItem]()

        override func viewDidLoad() {
        super.viewDidLoad()

        let asset1 = AVPlayerItem(url: url1)
        let asset2 = AVPlayerItem(url: url2)
        let asset3 = AVPlayerItem(url: url3)


        items = [asset1, asset2, asset3, asset4]

        queue = AVQueuePlayer(items: items)

    for item in queue.items() {
        NotificationCenter.default.addObserver(self, selector:#selector(playerItemDidReachEnd(notification:)),
           name: .AVPlayerItemDidPlayToEndTime, object: item)
    }
}

    @IBAction func pushButton1(_ sender: UIButton) {
        sender.isSelected = true
        queue.play()
    }

    @IBAction func pushButton2(sender: UIButton) {
        if self.lonelyPlayer == nil {

        }else {
            if (self.lonelyPlayer?.isPlaying)! {
                self.lonelyPlayer?.stop()
            }
        }
        audioPlayer(url: url1, buttonId: 1)    }

    @IBAction func pushButton3(sender: UIButton) {
        if self.lonelyPlayer == nil {

        }else {
            if (self.lonelyPlayer?.isPlaying)! {
                self.lonelyPlayer?.stop()
            }
        }
        audioPlayer(url: url2, buttonId: 2)
        }

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        if (self.currentPlayer == 1) {
            yourButton2.isSelected = false
        } else if (self.currentPlayer == 2) {
            yourButton3.isSelected = false
        } 
}

    func playerItemDidReachEnd(notification: NSNotification) {

        if notification.object as? AVPlayerItem == items[0] {
            yourButton1.isSelected = false
            yourButton2.isSelected = true
        }

        if notification.object as? AVPlayerItem == items[1] {
            yourButton2.isSelected = false
            yourButton3.isSelected = true
        }

    func audioPlayer(url: URL, buttonId: Int) {
        do {
            try lonelyPlayer = AVAudioPlayer(contentsOf:url)
            lonelyPlayer!.play()
            lonelyPlayer!.delegate = self
            yourButton2.isSelected = (buttonId == 1)
            yourButton3.isSelected = (buttonId == 2)
            currentPlayer = buttonId
        } catch {
            print(error)
        }
    }

Upvotes: 0

Views: 297

Answers (1)

Papershine
Papershine

Reputation: 5223

var queue = AVQueuePlayer()
var items = [AVPlayerItem]()
var currentlyPlaying = 0
var isPlaying = false {
    didSet{
        checkButtons()
    }
}

@IBOutlet weak var button1 : UIButton? //connect to button 1
@IBOutlet weak var button2 : UIButton? //connect to button 2
@IBOutlet weak var button3 : UIButton? //connect to button 3

override func viewDidLoad() {
    super.viewDidLoad()

    let asset1 = AVPlayerItem(url: url1)
    let asset2 = AVPlayerItem(url: url2)
    let asset3 = AVPlayerItem(url: url3)


    items = [asset1, asset2, asset3, asset4]

    queue = AVQueuePlayer(items: items)

    for item in queue.items() {
        NotificationCenter.default.addObserver(self, selector:#selector(playerItemDidReachEnd(notification:)), name: .AVPlayerItemDidPlayToEndTime, object: item)
    }
}

@IBAction func pushButton1(_ sender: UIButton) {
    self.currentlyPlaying = 1
    self.isPlaying = true
    sender.isSelected = true
    queue.play()
}

@IBAction func pushButton2(sender: UIButton) {
    self.currentlyPlaying = 2
    self.isPlaying = true
    if self.lonelyPlayer == nil {

    }else {
        if (self.lonelyPlayer?.isPlaying)! {
            self.lonelyPlayer?.stop()
        }
    }
    audioPlayer(url: url1, buttonId: 1)    
}

@IBAction func pushButton3(sender: UIButton) {
    self.currentlyPlaying = 3
    self.isPlaying = true
    if self.lonelyPlayer == nil {

    }else {
        if (self.lonelyPlayer?.isPlaying)! {
            self.lonelyPlayer?.stop()
        }
    }
    audioPlayer(url: url2, buttonId: 2)
}

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    if (self.currentPlayer == 1) {
        yourButton2.isSelected = false
    } else if (self.currentPlayer == 2) {
        yourButton3.isSelected = false
    } 
    self.isPlaying = false
}

func playerItemDidReachEnd(notification: NSNotification) {

    if notification.object as? AVPlayerItem == items[0] {
        yourButton1.isSelected = false
        yourButton2.isSelected = true
    }

    if notification.object as? AVPlayerItem == items[1] {
        yourButton2.isSelected = false
        yourButton3.isSelected = true
    }
    self.isPlaying = false
)

func audioPlayer(url: URL, buttonId: Int) {
    do {
        try lonelyPlayer = AVAudioPlayer(contentsOf:url)
        lonelyPlayer!.play()
        lonelyPlayer!.delegate = self
        yourButton2.isSelected = (buttonId == 1)
        yourButton3.isSelected = (buttonId == 2)
        currentPlayer = buttonId
    } catch {
        print(error)
    }
}

func checkButtons() {
    if isPlaying {
        switch currentlyPlaying {
        case 1:
            button2.isEnabled = false
            button3.isEnabled = false
        case 2:
            button1.isEnabled = false
            button3.isEnabled = false
        case 3:
            button1.isEnabled = false
            button2.isEnabled = false
        default:
            print("Something went wrong!")
        }
   } else {
        button1.isEnabled = true
        button2.isEnabled = true
        button3.isEnabled = true
   }
}

It disables the buttons when it is playing.

Note: this code hasn't been tested as I was writing it on the bus

EDIT: You can set the queue as an optional, then use queue.pause and then queue = nil to stop it. Remember to reallocate it before using it again!

Upvotes: 0

Related Questions