fix(audio): BGM 동시 호출 보호 추가

- _isBgmBusy 락으로 동시 작업 방지
- 대기열(_queuedBgm)로 마지막 요청만 처리
- Loading interrupted 에러 시 플레이어 재생성 방지
This commit is contained in:
JiWoong Sul
2026-01-08 19:54:43 +09:00
parent d1eeb7ca37
commit 76090a46b6

View File

@@ -85,6 +85,12 @@ class AudioService {
// 오디오 일시정지 상태 (앱 백그라운드 시)
bool _isPaused = false;
// BGM 작업 진행 중 여부 (동시 호출 방지)
bool _isBgmBusy = false;
// 대기 중인 BGM (작업 중 새 요청이 들어온 경우)
String? _queuedBgm;
// ─────────────────────────────────────────────────────────────────────────
// 초기화
// ─────────────────────────────────────────────────────────────────────────
@@ -202,16 +208,35 @@ class AudioService {
// BGM 재생
// ─────────────────────────────────────────────────────────────────────────
/// BGM 재생 (단순화된 버전)
/// BGM 재생 (동시 호출 보호)
///
/// 여러 곳에서 동시에 호출되어도 마지막 요청만 처리합니다.
/// 작업 중 새 요청이 들어오면 대기열에 저장하고 완료 후 재생합니다.
Future<void> playBgm(String name) async {
if (_isPaused) return;
if (!_staticInitialized) await init();
if (_currentBgm == name) return;
if (_staticBgmPlayer == null) return;
await _playBgmInternal(name);
// 작업 중이면 대기열에 저장 (마지막 요청만 유지)
if (_isBgmBusy) {
_queuedBgm = name;
debugPrint('[AudioService] BGM $name queued');
return;
}
_isBgmBusy = true;
try {
await _playBgmInternal(name);
} finally {
_isBgmBusy = false;
// 대기 중인 BGM이 있으면 재생
if (_queuedBgm != null && _queuedBgm != _currentBgm) {
final queued = _queuedBgm;
_queuedBgm = null;
await playBgm(queued!);
}
}
}
/// 내부 BGM 재생 (뮤텍스 내에서 호출)
@@ -236,15 +261,23 @@ class AudioService {
_userInteracted = true;
debugPrint('[AudioService] Playing BGM: $name');
} on PlayerInterruptedException catch (e) {
// 다른 BGM 요청으로 인한 중단 - 정상적인 상황
debugPrint('[AudioService] BGM $name interrupted: ${e.message}');
} catch (e) {
final errorStr = e.toString();
// "Loading interrupted"는 새 BGM 요청으로 인한 정상 중단
if (errorStr.contains('Loading interrupted') ||
errorStr.contains('abort')) {
debugPrint('[AudioService] BGM $name loading interrupted (new request)');
return; // 플레이어 재생성 불필요
}
debugPrint('[AudioService] BGM error: $errorStr');
// macOS Operation Stopped 에러: 플레이어 재생성 후 재시도
if (errorStr.contains('Operation Stopped') ||
errorStr.contains('-11849') ||
errorStr.contains('abort')) {
errorStr.contains('-11849')) {
debugPrint('[AudioService] Recreating BGM player...');
await _recreateBgmPlayer();