Files
PyQt6_LaTaniere/src/controllers/audio_controller.py
T
2026-03-26 20:48:02 +01:00

93 lines
3.2 KiB
Python

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)