jpsim / JPSVolumeButtonHandler

JPSVolumeButtonHandler provides an easy block interface to hardware volume buttons on iOS devices. Perfect for camera apps!
MIT License
333 stars 90 forks source link

playing sound while button is pressed #18

Closed lucatorella closed 8 years ago

lucatorella commented 8 years ago

While the volume button is pressed, if some conditions are met I'd like to play a sound. Unfortunately the sound often is kind of cut of. It is quite easy to reproduce, while the volume button is pressed, play a sound AudioServicesPlaySystemSound(self.beepSound). Is it happening because of the other audio session going on? Any idea how to solve it?

lucatorella commented 8 years ago

I include the code to reproduce the issue:

import UIKit
import MediaPlayer

class ViewController: UIViewController {

    private var beepSound: SystemSoundID = 0
    private var volumeButtonHandler: JPSVolumeButtonHandler?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let URL = NSBundle.mainBundle().URLForResource("beep", withExtension: "wav") {
            AudioServicesCreateSystemSoundID(URL, &beepSound)
        }

        volumeButtonHack()
    }

    private func volumeButtonHack() {
        let block = { [unowned self] () -> Void in
            AudioServicesPlaySystemSound(self.beepSound)
        }
        volumeButtonHandler = JPSVolumeButtonHandler(upBlock: block, downBlock: block)
    }
}
lucatorella commented 8 years ago

Actually it's much easier to reproduce:

    private func volumeButtonHack() {
        let block = { [unowned self] () -> Void in
            let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
            dispatch_after(delayTime, dispatch_get_main_queue()) {
                AudioServicesPlaySystemSound(self.beepSound)
            }
        }
        volumeButtonHandler = JPSVolumeButtonHandler(upBlock: block, downBlock: block)
    }

the solution is to use AVAudioPlayer instead of AudioServicesPlaySystemSound to play the sound. So this snippet works:

    override func viewDidLoad() {
            ...
            player = try! AVAudioPlayer(contentsOfURL: URL)
    }

    private func volumeButtonHack() {
        let block = { [unowned self] () -> Void in
            let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
            dispatch_after(delayTime, dispatch_get_main_queue()) {
                self.player.play()
            }
        }
        volumeButtonHandler = JPSVolumeButtonHandler(upBlock: block, downBlock: block)
    }