127 lines
3.5 KiB
Swift
127 lines
3.5 KiB
Swift
//
|
|
// AuditionSoundManager.swift
|
|
// SodaLive
|
|
//
|
|
// Created by klaus on 1/7/25.
|
|
//
|
|
|
|
import Foundation
|
|
import AVKit
|
|
import Combine
|
|
|
|
class AuditionSoundManager: NSObject, ObservableObject {
|
|
static let shared = AuditionSoundManager()
|
|
|
|
@Published private (set) var isPlaying = false
|
|
|
|
@Published var isLoading = false
|
|
@Published var errorMessage = ""
|
|
@Published var isShowPopup = false
|
|
|
|
@Published var currentTime: Double = 0.0
|
|
@Published private (set) var duration: Double = 0.0
|
|
|
|
private var player: AVAudioPlayer!
|
|
private var timer: Timer?
|
|
@Published private (set) var applicantId = -1
|
|
|
|
func resetPlayer() {
|
|
stop()
|
|
}
|
|
|
|
func playOrPause(applicantId: Int, url: String) {
|
|
if applicantId <= 0 {
|
|
stop()
|
|
}
|
|
|
|
if self.applicantId != applicantId {
|
|
stop()
|
|
setupPlayer(with: url)
|
|
self.applicantId = applicantId
|
|
} else {
|
|
if !isPlaying {
|
|
player?.play()
|
|
isPlaying = player?.isPlaying ?? false
|
|
startTimer()
|
|
} else {
|
|
player?.pause()
|
|
isPlaying = player?.isPlaying ?? false
|
|
stopTimer()
|
|
}
|
|
}
|
|
}
|
|
|
|
private func stop() {
|
|
stopTimer()
|
|
isPlaying = false
|
|
isLoading = false
|
|
player?.stop()
|
|
player?.currentTime = 0
|
|
currentTime = 0.0
|
|
duration = 0.0
|
|
applicantId = -1
|
|
}
|
|
|
|
private func setupPlayer(with url: String) {
|
|
guard let url = URL(string: url) else {
|
|
self.errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
|
|
self.isShowPopup = true
|
|
return
|
|
}
|
|
|
|
isLoading = true
|
|
URLSession.shared.dataTask(with: url) { [unowned self] data, response, error in
|
|
guard let audioData = data else {
|
|
self.isLoading = false
|
|
return
|
|
}
|
|
|
|
do {
|
|
self.player = try AVAudioPlayer(data: audioData)
|
|
|
|
DispatchQueue.main.async {
|
|
self.player?.volume = 1
|
|
self.player?.delegate = self
|
|
self.player?.prepareToPlay()
|
|
|
|
self.player?.play()
|
|
self.duration = self.player?.duration ?? 0.0
|
|
self.isPlaying = self.player.isPlaying
|
|
self.isLoading = false
|
|
self.startTimer()
|
|
}
|
|
} catch {
|
|
DispatchQueue.main.async {
|
|
self.errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
|
|
self.isShowPopup = true
|
|
self.isLoading = false
|
|
}
|
|
}
|
|
}.resume()
|
|
}
|
|
|
|
private func startTimer() {
|
|
stopTimer() // 기존 타이머 제거
|
|
timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in
|
|
self?.updateCurrentTime()
|
|
}
|
|
}
|
|
|
|
// 타이머 정지
|
|
private func stopTimer() {
|
|
timer?.invalidate()
|
|
timer = nil
|
|
}
|
|
|
|
private func updateCurrentTime() {
|
|
guard let audioPlayer = player else { return }
|
|
currentTime = audioPlayer.currentTime
|
|
}
|
|
}
|
|
|
|
extension AuditionSoundManager: AVAudioPlayerDelegate {
|
|
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
|
|
stop()
|
|
}
|
|
}
|