// =========================================================================== // FILE: lib/services/audio_service.dart // =========================================================================== import 'package:flutter/material.dart'; import 'package:audioplayers/audioplayers.dart'; import '../core/app_colors.dart'; import 'package:shared_preferences/shared_preferences.dart'; class AudioService extends ChangeNotifier { static final AudioService instance = AudioService._internal(); AudioService._internal(); bool isMuted = false; final AudioPlayer _sfxPlayer = AudioPlayer(); final AudioPlayer _bgmPlayer = AudioPlayer(); // Teniamo traccia del tema attuale per gestire bene quando togliamo il muto AppThemeType _currentTheme = AppThemeType.cyberpunk; Future init() async { // 1. Carica la preferenza salvata final prefs = await SharedPreferences.getInstance(); isMuted = prefs.getBool('isMuted') ?? false; // 2. Imposta la musica in loop infinito await _bgmPlayer.setReleaseMode(ReleaseMode.loop); } void toggleMute() async { isMuted = !isMuted; // Salva la scelta per il prossimo riavvio final prefs = await SharedPreferences.getInstance(); await prefs.setBool('isMuted', isMuted); if (isMuted) { await _bgmPlayer.pause(); } else { // Se togliamo il muto, facciamo ripartire la canzone del tema attuale playBgm(_currentTheme); } notifyListeners(); } // --- BGM (Musica di sottofondo) --- Future playBgm(AppThemeType theme) async { _currentTheme = theme; // Aggiorna sempre la memoria del tema // FERMA SEMPRE LA TRACCIA PRECEDENTE prima di far partire la nuova await _bgmPlayer.stop(); if (isMuted) return; String audioPath = ''; // Assegna a ogni tema la sua colonna sonora switch (theme) { case AppThemeType.cyberpunk: audioPath = 'audio/bgm/Cyber_Dystopia.mp3'; break; case AppThemeType.doodle: audioPath = 'audio/bgm/Quad_Dreams.mp3'; break; case AppThemeType.wood: audioPath = 'audio/bgm/Legno_Canopy.mp3'; break; case AppThemeType.arcade: audioPath = 'audio/bgm/8-bit_Prowler.mp3'; break; case AppThemeType.grimorio: audioPath = 'audio/bgm/Grimorio_Astral.mp3'; break; case AppThemeType.minimal: // Il tema minimal non ha musica (silenzio/focus) audioPath = ''; break; } if (audioPath.isNotEmpty) { try { // IL VOLUME VA PASSATO QUI (0.15 = 15%), sennĂ² viene ignorato! await _bgmPlayer.play(AssetSource(audioPath), volume: 0.15); } catch (e) { debugPrint("Errore riproduzione BGM: $e"); } } } Future stopBgm() async { await _bgmPlayer.stop(); } // --- SFX (Effetti sonori) --- void playLineSfx(AppThemeType theme) async { if (isMuted) return; String file = ''; switch (theme) { case AppThemeType.minimal: case AppThemeType.arcade: file = 'minimal_line.wav'; break; case AppThemeType.doodle: case AppThemeType.wood: file = 'doodle_line.wav'; break; case AppThemeType.cyberpunk: case AppThemeType.grimorio: file = 'cyber_line.wav'; break; } if (file.isNotEmpty) { try { // Effetti sonori forzati al 100% await _sfxPlayer.play(AssetSource('audio/sfx/$file'), volume: 1.0); } catch (e) { debugPrint("Errore SFX Linea non trovato: $file"); } } } void playBoxSfx(AppThemeType theme) async { if (isMuted) return; String file = ''; switch (theme) { case AppThemeType.minimal: case AppThemeType.arcade: file = 'minimal_box.wav'; break; case AppThemeType.doodle: case AppThemeType.wood: file = 'doodle_box.wav'; break; case AppThemeType.cyberpunk: case AppThemeType.grimorio: file = 'cyber_box.wav'; break; } if (file.isNotEmpty) { try { await _sfxPlayer.play(AssetSource('audio/sfx/$file'), volume: 1.0); } catch (e) { debugPrint("Errore SFX Box non trovato: $file"); } } } void playBonusSfx() async { if (isMuted) return; try { await _sfxPlayer.play(AssetSource('audio/sfx/bonus.wav'), volume: 1.0); } catch(e) {} } void playBombSfx() async { if (isMuted) return; try { await _sfxPlayer.play(AssetSource('audio/sfx/bomb.wav'), volume: 1.0); } catch(e) {} } }