fix(audio): BGM 동시 호출 보호 추가
- _isBgmBusy 락으로 동시 작업 방지 - 대기열(_queuedBgm)로 마지막 요청만 처리 - Loading interrupted 에러 시 플레이어 재생성 방지
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user