refactor(core/audio): Audio owns the engine (migration)

Audio guanya un std::unique_ptr<Ja::Engine> engine_ com a membre privat.
Es construeix a initSDLAudio amb els defaults de Defaults::Audio; es
destrueix sol al ~Audio (cap Ja::quit() explícit).

Totes les crides Ja::funcióN(...) d'audio.cpp passen a engine_->funcióN:
  - playMusicInternal: crossfadeMusic/stopMusic/playMusic
  - pauseMusic, resumeMusic, stopMusic, fadeOutMusic
  - playSound x2, stopAllSounds
  - setSoundVolume, setMusicVolume
  - getMusicState (via instance->engine_ — és static però pot arribar-hi)

Les free functions forwarder del commit 2 (Ja::init/quit/update/playMusic/
pauseMusic/resumeMusic/stopMusic/fadeOutMusic/crossfadeMusic/
getMusicState/setMusicVolume/enableMusic i els equivalents de so) es
retiren del .hpp i del .cpp: ja no les crida ningú.

Queden com a free functions permanents (les usa Resource::Cache):
loadMusic (x2), loadSound, deleteMusic, deleteSound. Aquests darrers
consulten Engine::active() per notificar el motor abans d'alliberar.

audio.hpp forward-declara també `class Ja::Engine` perquè engine_ és
un std::unique_ptr i el dtor es defineix out-of-line al .cpp (= default)
— així no cal incloure jail_audio.hpp al header.

Els NOLINT(readability-make-member-function-const) d'audio.cpp es
mantenen amb raó actualitzada: std::unique_ptr::operator-> retorna T*
(no const T*), per tant clang-tidy veu un mètode d'Audio que podria ser
const encara que muti l'Engine via el punter. La mutació és real; el
NOLINT segueix sent honest.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
JailDesignerandClaude Opus 4.7 committed 2026-04-20 13:25:03 +02:00
1 parent 1d124e967d
commit 961a59c460
4 files changed
+50 -165

No files matched your search

+38 -38
View File
@@ -31,15 +31,14 @@ auto Audio::get() -> Audio* { return Audio::instance.get(); }
Audio::Audio(const Config& config)
: config_(config) { initSDLAudio(); }
// Destructor
Audio::~Audio() {
Ja::quit();
}
// Destructor: engine_ és std::unique_ptr, el seu dtor tanca el device SDL i
// desregistra Ja::Engine::active_. Cap crida explícita necessària.
Audio::~Audio() = default;
// Mètode principal: l'estat de la música el manté Ja (única font de veritat),
// per tant no cal cap sincronització aquí.
// Mètode principal: l'estat de la música el manté el motor (única font de
// veritat), per tant no cal cap sincronització aquí.
void Audio::update() {
Ja::update();
if (instance && instance->engine_) { instance->engine_->update(); }
}
// Reprodueix la música per nom (amb crossfade opcional)
@@ -78,70 +77,70 @@ void Audio::playMusic(Ja::Music* music, const int loop, const int crossfade_ms)
void Audio::playMusicInternal(Ja::Music* music, const int loop, const int crossfade_ms) {
const bool CURRENTLY_PLAYING = (getMusicState() == MusicState::PLAYING);
if (crossfade_ms > 0 && CURRENTLY_PLAYING) {
Ja::crossfadeMusic(music, crossfade_ms, loop);
engine_->crossfadeMusic(music, crossfade_ms, loop);
} else {
if (CURRENTLY_PLAYING) {
Ja::stopMusic();
engine_->stopMusic();
}
Ja::playMusic(music, loop);
engine_->playMusic(music, loop);
}
music_.loop = (loop != 0);
}
// Pausa la música (l'estat el transiciona Ja::pauseMusic)
// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::current_music->state
// Pausa la música (l'estat el transiciona Engine::pauseMusic)
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::pauseMusic() {
if (music_enabled_ && getMusicState() == MusicState::PLAYING) {
Ja::pauseMusic();
engine_->pauseMusic();
}
}
// Continua la música pausada (l'estat el transiciona Ja::resumeMusic)
// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::current_music->state
// Continua la música pausada (l'estat el transiciona Engine::resumeMusic)
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::resumeMusic() {
if (music_enabled_ && getMusicState() == MusicState::PAUSED) {
Ja::resumeMusic();
engine_->resumeMusic();
}
}
// Detiene la música (l'estat el transiciona Ja::stopMusic)
// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::current_music/outgoing_music
// Atura la música (l'estat el transiciona Engine::stopMusic)
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::stopMusic() {
if (music_enabled_) {
Ja::stopMusic();
engine_->stopMusic();
}
}
// Reprodueix un so per nom
// NOLINTNEXTLINE(readability-make-member-function-const) — muta globals de Ja::channels
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::playSound(const std::string& name, Group group) {
if (sound_enabled_) {
Ja::playSound(AudioResource::getSound(name), 0, static_cast<int>(group));
engine_->playSound(AudioResource::getSound(name), 0, static_cast<int>(group));
}
}
// Reprodueix un so per punter directe
// NOLINTNEXTLINE(readability-make-member-function-const) — muta globals de Ja::channels
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::playSound(Ja::Sound* sound, Group group) {
if (sound_enabled_ && sound != nullptr) {
Ja::playSound(sound, 0, static_cast<int>(group));
engine_->playSound(sound, 0, static_cast<int>(group));
}
}
// Atura tots els sons
// NOLINTNEXTLINE(readability-make-member-function-const) — muta globals de Ja::channels
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::stopAllSounds() {
if (sound_enabled_) {
Ja::stopChannel(-1);
engine_->stopChannel(-1);
}
}
// Fa una fosa de sortida de la música
// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::outgoing_music/incoming_fade
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::fadeOutMusic(int milliseconds) {
if (music_enabled_ && getMusicState() == MusicState::PLAYING) {
Ja::fadeOutMusic(milliseconds);
engine_->fadeOutMusic(milliseconds);
}
}
@@ -149,7 +148,8 @@ void Audio::fadeOutMusic(int milliseconds) {
// exposa Audio (INVALID/DISABLED de Ja col·lapsen a STOPPED — la capa d'usuari
// només vol saber si està sonant, pausat o parat).
auto Audio::getMusicState() -> MusicState {
switch (Ja::getMusicState()) {
if (!instance || !instance->engine_) { return MusicState::STOPPED; }
switch (instance->engine_->getMusicState()) {
case Ja::MusicState::PLAYING:
return MusicState::PLAYING;
case Ja::MusicState::PAUSED:
@@ -171,15 +171,15 @@ auto Audio::effectiveVolume(float volume, bool channel_enabled) const -> float {
}
// Estableix el volum dels sons (float 0.0..1.0)
// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::sound_volume[] i canals actius
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::setSoundVolume(float sound_volume, Group group) {
Ja::setSoundVolume(effectiveVolume(sound_volume, sound_enabled_), static_cast<int>(group));
engine_->setSoundVolume(effectiveVolume(sound_volume, sound_enabled_), static_cast<int>(group));
}
// Estableix el volum de la música (float 0.0..1.0)
// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::music_volume i stream actual
// NOLINTNEXTLINE(readability-make-member-function-const) — muta estat via engine_; unique_ptr::operator-> no propaga const
void Audio::setMusicVolume(float music_volume) {
Ja::setMusicVolume(effectiveVolume(music_volume, music_enabled_));
engine_->setMusicVolume(effectiveVolume(music_volume, music_enabled_));
}
// Aplica una nova configuració (substitueix la config cachejada i reaplica enables/volums)
@@ -212,14 +212,14 @@ void Audio::enableMusic(bool value) {
setMusicVolume(config_.music_volume);
}
// Inicialitza SDL Audio
// Inicialitza SDL Audio i el motor Ja::Engine owned.
void Audio::initSDLAudio() {
if (!SDL_Init(SDL_INIT_AUDIO)) {
std::fprintf(stderr, "Audio: SDL_AUDIO could not initialize! SDL Error: %s\n", SDL_GetError());
} else {
Ja::init(Defaults::Audio::FREQUENCY, Defaults::Audio::FORMAT, Defaults::Audio::CHANNELS);
sound_enabled_ = config_.sound_enabled;
music_enabled_ = config_.music_enabled;
enable(config_.enabled);
return;
}
engine_ = std::make_unique<Ja::Engine>(Defaults::Audio::FREQUENCY, Defaults::Audio::FORMAT, Defaults::Audio::CHANNELS);
sound_enabled_ = config_.sound_enabled;
music_enabled_ = config_.music_enabled;
enable(config_.enabled);
}