So I have a class called audio settings that is as follows:
class audioSettings: ObservableObject {
var audioPlayer: AVAudioPlayer?
var playing = false
var playValue: TimeInterval = 0.0
var playerDuration: TimeInterval = 146
var timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
func playSound(sound: String, type: String) {
if let path = Bundle.main.path(forResource: sound, ofType: type) {
do {
if playing == false {
if (audioPlayer == nil) {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
audioPlayer?.prepareToPlay()
audioPlayer?.play()
playing = true
}
}
if playing == false {
audioPlayer?.play()
playing = true
}
} catch {
print("Could not find and play the sound file.")
}
}
}
func stopSound() {
// if playing == true {
audioPlayer?.stop()
audioPlayer = nil
playing = false
playValue = 0.0
// }
}
func pauseSound() {
if playing == true {
audioPlayer?.pause()
playing = false
}
}
func changeSliderValue() {
if playing == true {
pauseSound()
audioPlayer?.currentTime = playValue
}
if playing == false {
audioPlayer?.play()
playing = true
}
}
}
And when I implement the code in to the view I have success with playing the file. I have success with stopping it and I have success with moving the slider and getting a new position in the audio.
Where i'm struggling is in getting the slider to update in real time as the audio is playing. If I hit play the slider will do nothing until I hit pause. At which point it will move to the correct position.
Here is the views code:
struct myExperienceFearChunk: View {
@ObservedObject var audiosettings = audioSettings()
var body: some View {
HStack {
Button(action: {
if (self.playButton == Image(systemName: "play.circle")) {
print("All Done")
self.audiosettings.playSound(sound: "audio file", type: "mp3")
self.audiosettings.timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
self.playButton = Image(systemName: "pause.circle")
} else {
self.audiosettings.pauseSound()
self.playButton = Image(systemName: "play.circle")
}
}) {
self.playButton
.foregroundColor(Color.white)
.font(.system(size: 44))
}
Button(action: {
print("All Done")
self.audiosettings.stopSound()
self.playButton = Image(systemName: "play.circle")
self.audiosettings.playValue = 0.0
}) {
self.stopButton
.foregroundColor(Color.white)
.font(.system(size: 44))
}
}
Slider(value: $audiosettings.playValue, in: TimeInterval(0.0)...audiosettings.playerDuration, onEditingChanged: { _ in
self.audiosettings.changeSliderValue()
})
.onReceive(audiosettings.timer) { _ in
if self.audiosettings.playing {
if let currentTime = self.audiosettings.audioPlayer?.currentTime {
self.audiosettings.playValue = currentTime
if currentTime == TimeInterval(0.0) {
self.audiosettings.playing = false
}
}
}
else {
self.audiosettings.playing = false
self.audiosettings.timer.upstream.connect().cancel()
}
}
}
}
}
I know that the .onReceive is where the slider is being updated from when I hit pause, as without it the slider doesn't update at all unless dragged.
Any ideas how I can get the slider to update as the audio is playing setting the playValue as it goes.
Thanks.