import tempfile import cyminiaudio as cma from PySide6.QtCore import QFile from config.config_manager import ConfigManager, VOLUME_KEY from config.constants import Resources class AudioController: # Encapsule toute la logique audio : lecture, volume, mute. def __init__(self, config: ConfigManager, slider, mute_btn): self._config = config self._slider = slider self._mute_btn = mute_btn # Chargement du MP3 depuis les ressources Qt mp3file = QFile(Resources.MP3.value) mp3file.open(QFile.ReadOnly) mp3data = mp3file.readAll().data() mp3file.close() # 2. Créer un fichier temporaire "invisible" pour l'utilisateur self.tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") self.tmp.write(mp3data) self.tmp.close() # Libère le verrou pour le lecteur # État initial du lecteur volume = config.get_volume() self._is_muted = (volume == 0) self._previous_volume = volume if volume != 0 else config.get_default(VOLUME_KEY) self._apply_volume(volume, save=False) self._refresh_mute_btn() # 3. Initialiser le moteur SANS le bloc 'with' # En les stockant dans self, ils restent vivants en mémoire self._audio_engine = cma.Engine() self._sound = self._audio_engine.play(self.tmp.name) self._sound.looping = True # On force le volume du son pour correspondre à la config self._sound.volume = volume / 100.0 # Connexions self._slider.valueChanged.connect(self._on_slider_changed) self._mute_btn.clicked.connect(self.toggle_mute) # ------------------------------------------------------------------ # Public API # ------------------------------------------------------------------ def toggle_mute(self) -> None: if not self._is_muted: self._previous_volume = self._slider.value() self._apply_volume(0) self._is_muted = True else: self._apply_volume(self._previous_volume) self._is_muted = False # ------------------------------------------------------------------ # Private helpers # ------------------------------------------------------------------ def _on_slider_changed(self, value: int) -> None: self._is_muted = value == 0 if hasattr(self, '_sound'): # cyminiaudio attend souvent un float entre 0.0 et 1.0 self._sound.volume = value / 100.0 self._config.set_volume(value) self._refresh_mute_btn() def _apply_volume(self, value: int, save: bool = True) -> None: self._slider.blockSignals(True) self._slider.setValue(value) self._slider.blockSignals(False) # Même correction ici if hasattr(self, '_sound'): self._sound.volume = value / 100.0 if save: self._config.set_volume(value) self._refresh_mute_btn() def _refresh_mute_btn(self) -> None: muted = self._slider.value() == 0 self._mute_btn.setProperty("muted", muted) self._mute_btn.style().unpolish(self._mute_btn) self._mute_btn.style().polish(self._mute_btn)