refactor(audio): BGM 재생 로직 단순화

- 뮤텍스 패턴 제거 (불필요한 복잡성)
- 단순화된 playBgm 메서드
This commit is contained in:
JiWoong Sul
2026-01-07 20:59:03 +09:00
parent d63463a677
commit 464e5e9c22

View File

@@ -1,4 +1,4 @@
import 'dart:async' show Completer, unawaited; import 'dart:async' show Completer;
import 'package:flutter/foundation.dart' show debugPrint, kIsWeb; import 'package:flutter/foundation.dart' show debugPrint, kIsWeb;
import 'package:just_audio/just_audio.dart'; import 'package:just_audio/just_audio.dart';
@@ -6,43 +6,6 @@ import 'package:just_audio/just_audio.dart';
import 'package:asciineverdie/src/core/audio/sfx_channel_pool.dart'; import 'package:asciineverdie/src/core/audio/sfx_channel_pool.dart';
import 'package:asciineverdie/src/core/storage/settings_repository.dart'; import 'package:asciineverdie/src/core/storage/settings_repository.dart';
/// BGM 작업 직렬화를 위한 간단한 뮤텍스
class _BgmMutex {
Completer<void>? _completer;
String? _pendingBgm;
/// 현재 작업 중인지 확인
bool get isLocked => _completer != null && !_completer!.isCompleted;
/// 락 획득 시도 (이미 잠겨있으면 대기 BGM 설정 후 false 반환)
Future<bool> tryAcquire(String bgmName) async {
if (isLocked) {
// 이미 작업 중이면 대기 BGM 설정 (마지막 것만 유지)
_pendingBgm = bgmName;
return false;
}
_completer = Completer<void>();
return true;
}
/// 락 해제 및 대기 중인 BGM 반환
String? release() {
_completer?.complete();
_completer = null;
final pending = _pendingBgm;
_pendingBgm = null;
return pending;
}
/// 강제 해제 (에러 시)
void forceRelease() {
if (_completer != null && !_completer!.isCompleted) {
_completer!.complete();
}
_completer = null;
}
}
/// 게임 오디오 서비스 (싱글톤, 핫 리로드 안전) /// 게임 오디오 서비스 (싱글톤, 핫 리로드 안전)
/// ///
/// BGM과 SFX를 관리하며, 설정과 연동하여 볼륨을 조절합니다. /// BGM과 SFX를 관리하며, 설정과 연동하여 볼륨을 조절합니다.
@@ -122,9 +85,6 @@ class AudioService {
// 오디오 일시정지 상태 (앱 백그라운드 시) // 오디오 일시정지 상태 (앱 백그라운드 시)
bool _isPaused = false; bool _isPaused = false;
// BGM 작업 직렬화 뮤텍스 (동시 호출 방지)
final _bgmMutex = _BgmMutex();
// ───────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────
// 초기화 // 초기화
// ───────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────
@@ -242,32 +202,17 @@ class AudioService {
// BGM 재생 // BGM 재생
// ───────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────
/// BGM 재생 (뮤텍스로 동시 호출 방지) /// BGM 재생 (단순화된 버전)
/// ///
/// 여러 곳에서 동시에 호출되어도 안전하게 처리합니다. /// 여러 곳에서 동시에 호출되어도 마지막 요청만 처리합니다.
/// 진행 중인 작업이 있으면 대기열에 추가하고, 완료 후 마지막 요청만 실행합니다.
Future<void> playBgm(String name) async { Future<void> playBgm(String name) async {
if (_isPaused) return; if (_isPaused) return;
if (!_staticInitialized) await init(); if (!_staticInitialized) await init();
if (_currentBgm == name) return; if (_currentBgm == name) return;
if (_staticBgmPlayer == null) return; if (_staticBgmPlayer == null) return;
// 뮤텍스 획득 시도 (실패하면 대기열에 추가) debugPrint('[AudioService] playBgm requested: $name');
if (!await _bgmMutex.tryAcquire(name)) { await _playBgmInternal(name);
debugPrint('[AudioService] BGM $name queued (mutex locked)');
return;
}
try {
await _playBgmInternal(name);
} finally {
// 락 해제 및 대기 중인 BGM 확인
final pendingBgm = _bgmMutex.release();
if (pendingBgm != null && pendingBgm != _currentBgm) {
// 대기 중인 BGM이 있으면 재귀 호출 (새 뮤텍스 획득)
unawaited(playBgm(pendingBgm));
}
}
} }
/// 내부 BGM 재생 (뮤텍스 내에서 호출) /// 내부 BGM 재생 (뮤텍스 내에서 호출)