b183b3f3e5b09185819bc121de3a8b6f9f1a2d75
cambiarActivo persisted BEFORE telling the audio engine, so two quick taps raced on a SharedPreferences write. When the first write resolved last, the engine received the FIRST tap's value after the second one: the checkbox read enabled while the sound stayed flat, and toggling again could invert it the other way. Reported as the equalizer connecting and disconnecting at random and the checkbox disagreeing with what is audible. Reorder to engine first, disk last. The engine call is now issued before any await, so overlapping taps reach it in tap order and the last tap wins. Each subsequent step re-checks _activo, so a call that a newer tap superseded mid-flight neither applies a preset nor persists a value the user has already changed their mind about. Persisting last also puts what the user HEARS ahead of what is merely stored. The regression test drives two opposite taps through a persistence fake whose FIRST write is the slow one — the exact ordering hazard — and asserts the engine ends matching the state the UI shows. It fails on the previous ordering and passes on this one. An earlier attempt serialized every engine mutation through a shared Future lane. It fixed this case and deadlocked four widget tests: the lane field outlived a tester.runAsync block, so a future created in the real async zone was later chained from the fake-async zone that never advances it. Reverted in favour of the ordering fix, which needs no cross-zone state. Only the enable toggle is addressed here. The other reported symptom — equalization seeming to come and go while playing — is not explained by this race and is still open; the handler rebuilds the whole AndroidEqualizer on every player recreation, which is the next place to look.
PluriWave
Radio mundial con ecualizador personalizable, reconocimiento de canciones y UI premium.
Features
- +53.000 emisoras de 238 países (Radio Browser API)
- Ecualizador por emisora — guarda tu preset favorito para cada radio
- Reconocimiento de canciones — "¿Qué suena?" sin salir de la app
- Timer de auto-apagado — perfecto para dormir
- Reproducción en segundo plano — sigue sonando con la pantalla apagada
- Favoritos — acceso rápido a emisoras preferidas
- Compartir — envía emisoras a tus amigos
- UI premium — Material You, visualizador de audio, animaciones fluidas
Monetización
- 14 días PRO gratis al instalar
- Free: radio + favoritos + timer + background (con ads)
- PRO €2.99/año: sin ads + ecualizador + reconocimiento ilimitado
Stack
- Frontend: Flutter (Android + iOS)
- Radio API: Radio Browser (gratis, +53K emisoras)
- Audio: just_audio + audio_service
- Ecualizador: just_audio equalizer (Android nativo)
- Reconocimiento: AudD API (1000 req/mes free)
- Ads: Google AdMob
- Compras: in_app_purchase
CI/CD
Workflow Gitea Actions en .gitea/workflows/ci.yml, runner macmini-flutter.
Jobs: flutter pub get → flutter test → build apk --release → build appbundle --release
Artifacts: APK y AAB guardados en Gitea con nombre pluriwave-apk-<sha> / pluriwave-aab-<sha>.
Notificaciones: Telegram al completar (éxito ✅ / fallo ❌).
Secrets necesarios en el repo:
| Secret | Uso |
|---|---|
TELEGRAM_BOT_TOKEN |
Notificaciones CI |
TELEGRAM_CHAT_ID |
Canal de destino |
Signing: build de release usa clave debug (válido para CI interno). Para Play Store se requiere keystore como secret adicional.
Desarrollador
FreeTimeLab — freetimelab.es
Licencia
MIT
Description
PluriWave — Radio mundial con ecualizador, reconocimiento de canciones y UI premium
49 MiB
Languages
Dart
86%
HTML
7.1%
Kotlin
5.1%
JavaScript
1.6%
Swift
0.1%