From 66c58017251ebd239c37361bef3daa8648ff4d5d Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 20 Apr 2026 12:15:49 +0200 Subject: [PATCH] =?UTF-8?q?refactor(core/audio):=20Ja::*=20=C3=A9s=20l'?= =?UTF-8?q?=C3=BAnica=20font=20de=20veritat=20de=20MusicState=20(INCONS-02?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit music_.state era una cache d'estat que podia divergir del real — precisament per això existia getRealMusicState() com a "consulta honesta". Es descarta la cache: - music_.state deixa d'existir; el struct privat Music només manté name i loop. - getMusicState() passa a ser static i consulta Ja::getMusicState(), projectant INVALID/DISABLED al STOPPED que exposa Audio::MusicState. - getRealMusicState() desapareix (getMusicState ja fa la consulta real). - update() ja no necessita el bloc de sincronització. - playMusicInternal/pauseMusic/resumeMusic/stopMusic/fadeOutMusic llegeixen getMusicState() en comptes de music_.state i deixen de reassignar-lo — Ja ja ho fa. Externament: cap caller usa getMusicState/getRealMusicState, així que canviar a static és segur (Audio::get()->getMusicState() continua funcionant). pauseMusic/resumeMusic/stopMusic es marquen amb NOLINT per readability-make-member-function-const pel mateix motiu que INCONS-01 (muten globals de Ja::* que clang-tidy no veu). Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/audit-core-audio.md | 4 ++-- source/core/audio/audio.cpp | 48 ++++++++++++++++++------------------- source/core/audio/audio.hpp | 8 +++---- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/docs/audit-core-audio.md b/docs/audit-core-audio.md index cf1a506..abdc44f 100644 --- a/docs/audit-core-audio.md +++ b/docs/audit-core-audio.md @@ -20,7 +20,7 @@ Los IDs se mantienen estables una vez asignados. Cada entrada apunta al(los) fic |----|--------|--------| | COUP-01 | Encapsular globals `Ja::` en clase (engine sin estado global) | PENDING | | HC-02 | Formato/canales/freq hardcodeado en 3+ sitios | DONE | -| INCONS-02 | Doble `MusicState` + `getRealMusicState` como cache paralelo | PENDING | +| INCONS-02 | Doble `MusicState` + `getRealMusicState` como cache paralelo | DONE | | HC-01 | Parámetros de audio no configurables (viola convención del proyecto) | DONE | | PATCH-01 | `toggleEnabled/toggleSound/toggleMusic` no reaplican volumen | DONE | @@ -71,7 +71,7 @@ Los IDs se mantienen estables una vez asignados. Cada entrada apunta al(los) fic | ID | Fichero:línea | Hallazgo | Severidad | Estado | Notas | |----|---------------|----------|-----------|--------|-------| | INCONS-01 | `audio.cpp:128,135,142,149,172,180` | Métodos `const` que mutan globals de `Ja` (const miente) | Importante | DONE | `const` tret de 6 mètodes (`playSound` x2, `stopAllSounds`, `fadeOutMusic`, `setSoundVolume`, `setMusicVolume`). `effectiveVolume` es queda `const` (pur sobre membres). Cap caller extern via `const Audio*` | -| INCONS-02 | `audio.hpp:44-48` + `jail_audio.hpp:44-50` | Dos `MusicState` paralelos + `getRealMusicState` como puente | Importante | PENDING | Un enum único; eliminar `getRealMusicState` | +| INCONS-02 | `audio.hpp:44-48` + `jail_audio.hpp:44-50` | Dos `MusicState` paralelos + `getRealMusicState` como puente | Importante | DONE | Eliminat `music_.state` (cache) i `getRealMusicState`. `getMusicState()` consulta Ja::* directament i projecta INVALID/DISABLED → STOPPED. La font de veritat passa a ser Ja. `update()` ja no necessita sincronització | | INCONS-03 | `audio.cpp` varios | Comentarios mezclan catalán y español | Menor | PENDING | Unificar a catalán | | INCONS-04 | `audio.hpp:70,78` | `playMusic` `loop=-1` vs `playSound` `loop=0` | Menor | WONTFIX | Convención razonable (música loop / sonido one-shot); documentar | | INCONS-05 | `audio.hpp:102-105` | 4 formas de enable/disable sound (API redundante) + divergencia con `Ja::enableSound` | Importante | PENDING | Dejar `enableSound(bool)` + `toggleSound()`; delegar a `Ja` | diff --git a/source/core/audio/audio.cpp b/source/core/audio/audio.cpp index 74caac1..f10eed9 100644 --- a/source/core/audio/audio.cpp +++ b/source/core/audio/audio.cpp @@ -51,14 +51,10 @@ Audio::~Audio() { Ja::quit(); } -// Método principal +// Método principal: l'estat de la música el manté Ja (única font de veritat), +// per tant no cal cap sincronització aquí. void Audio::update() { Ja::update(); - - // Sincronitzar estat: detectar quan la música s'ha parat (p. ex. fade-out completat) - if (instance && instance->music_.state == MusicState::PLAYING && Ja::getMusicState() != Ja::MusicState::PLAYING) { - instance->music_.state = MusicState::STOPPED; - } } // Reproduce la música por nombre (con crossfade opcional) @@ -66,7 +62,7 @@ void Audio::playMusic(const std::string& name, const int loop, const int crossfa const bool NEW_LOOP = (loop != 0); // Si ja sona exactament la mateixa pista i mateix mode loop, no fem res - if (music_.state == MusicState::PLAYING && music_.name == name && music_.loop == NEW_LOOP) { + if (getMusicState() == MusicState::PLAYING && music_.name == name && music_.loop == NEW_LOOP) { return; } @@ -88,43 +84,44 @@ void Audio::playMusic(Ja::Music* music, const int loop, const int crossfade_ms) } // Camí comú dels dos overloads: fa el dispatch crossfade vs stop+play i -// actualitza state/loop. Els callers s'encarreguen del gating (music_enabled_, -// nullptr, same-track early return) i d'actualitzar music_.name. +// actualitza el loop cachejat. Els callers s'encarreguen del gating +// (music_enabled_, nullptr, same-track early return) i del nom. L'estat el +// manté Ja (Ja::playMusic posa PLAYING al Ja::Music* corresponent). void Audio::playMusicInternal(Ja::Music* music, const int loop, const int crossfade_ms) { - if (crossfade_ms > 0 && music_.state == MusicState::PLAYING) { + const bool CURRENTLY_PLAYING = (getMusicState() == MusicState::PLAYING); + if (crossfade_ms > 0 && CURRENTLY_PLAYING) { Ja::crossfadeMusic(music, crossfade_ms, loop); } else { - if (music_.state == MusicState::PLAYING) { + if (CURRENTLY_PLAYING) { Ja::stopMusic(); } Ja::playMusic(music, loop); } music_.loop = (loop != 0); - music_.state = MusicState::PLAYING; } -// Pausa la música +// Pausa la música (l'estat el transiciona Ja::pauseMusic) +// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::current_music->state void Audio::pauseMusic() { - if (music_enabled_ && music_.state == MusicState::PLAYING) { + if (music_enabled_ && getMusicState() == MusicState::PLAYING) { Ja::pauseMusic(); - music_.state = MusicState::PAUSED; } } -// Continua la música pausada +// Continua la música pausada (l'estat el transiciona Ja::resumeMusic) +// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::current_music->state void Audio::resumeMusic() { - if (music_enabled_ && music_.state == MusicState::PAUSED) { + if (music_enabled_ && getMusicState() == MusicState::PAUSED) { Ja::resumeMusic(); - music_.state = MusicState::PLAYING; } } -// Detiene la música +// Detiene la música (l'estat el transiciona Ja::stopMusic) +// NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::current_music/outgoing_music void Audio::stopMusic() { if (music_enabled_) { Ja::stopMusic(); - music_.state = MusicState::STOPPED; } } @@ -155,15 +152,16 @@ void Audio::stopAllSounds() { // Realiza un fundido de salida de la música // NOLINTNEXTLINE(readability-make-member-function-const) — muta Ja::outgoing_music/incoming_fade void Audio::fadeOutMusic(int milliseconds) { - if (music_enabled_ && getRealMusicState() == MusicState::PLAYING) { + if (music_enabled_ && getMusicState() == MusicState::PLAYING) { Ja::fadeOutMusic(milliseconds); } } -// Consulta directament l'estat real de la música a jail_audio -auto Audio::getRealMusicState() -> MusicState { - const Ja::MusicState JA_STATE = Ja::getMusicState(); - switch (JA_STATE) { +// Consulta directament l'estat a Ja i el projecta al subconjunt d'estats que +// 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()) { case Ja::MusicState::PLAYING: return MusicState::PLAYING; case Ja::MusicState::PAUSED: diff --git a/source/core/audio/audio.hpp b/source/core/audio/audio.hpp index ebcc57e..15013db 100644 --- a/source/core/audio/audio.hpp +++ b/source/core/audio/audio.hpp @@ -111,16 +111,14 @@ class Audio { [[nodiscard]] auto isEnabled() const -> bool { return enabled_; } [[nodiscard]] auto isSoundEnabled() const -> bool { return sound_enabled_; } [[nodiscard]] auto isMusicEnabled() const -> bool { return music_enabled_; } - [[nodiscard]] auto getMusicState() const -> MusicState { return music_.state; } - [[nodiscard]] static auto getRealMusicState() -> MusicState; + [[nodiscard]] static auto getMusicState() -> MusicState; // Estat real consultat a Ja:: [[nodiscard]] auto getCurrentMusicName() const -> const std::string& { return music_.name; } private: // --- Tipos anidados --- struct Music { - MusicState state{MusicState::STOPPED}; // Estado actual de la música - std::string name; // Última pista de música reproducida - bool loop{false}; // Indica si se reproduce en bucle + std::string name; // Última pista de música reproducida (buida si es va passar per punter sense filename) + bool loop{false}; // Si el play actual és en bucle }; // --- Métodos ---