Files
Noxely/CHANGELOG.md
T
tuxgyver ed1d40826b Noxely se sépare en client et serveur (2.0.0)
Le téléphone balayait quarante radios toutes les trois minutes, cherchait dans
quatre catalogues et enregistrait des directs. Tout cela le tenait éveillé pour
un travail qui n'a aucune raison de se faire sur batterie.

Un serveur reprend la collecte : recherche, guet, enregistrement, file de
téléchargement, piloté depuis un navigateur. Le mobile demande ce qui a changé
depuis son curseur, télécharge et se rendort — toutes les six heures, en Wi-Fi
non facturé. Vingt fichiers quittent l'application au passage.

Le balayage devient continu plutôt qu'espacé de trois minutes : une sonde ne lit
que le premier bloc de métadonnées avant de refermer, ce qui rend la permanence
tenable quand garder les flux ouverts coûterait plusieurs mégabits par seconde.
Un morceau guetté a été capté en moins de vingt-cinq secondes. La recherche
interroge les quatre catalogues à la fois et fond leurs résultats, les plus
légers d'abord.

Quatre défauts corrigés en chemin, tous trouvés en essayant plutôt qu'en
relisant : un jeton régénéré à chaque démarrage, qui aurait obligé à
reconfigurer le mobile ; un 403 de Wikimedia dû à un agent trop générique, que
la fusion des sources masquait ; un dossier de données par défaut inaccessible
au compte qui lance le serveur ; et une lecture de métadonnées qui n'itérait
rien, faute d'être asynchrone.
2026-09-13 17:39:43 +02:00

250 lines
14 KiB
Markdown

# Changelog
Toutes les évolutions notables de Noxely sont documentées ici.
Le format suit [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/)
et le versionnage [SemVer](https://semver.org/lang/fr/).
## [2.0.0] — 2026-09-13
Noxely se sépare en deux : un **serveur** qui collecte, un **mobile** qui écoute. Tout ce qui
tenait le téléphone éveillé a migré ailleurs — c'est la raison d'être de cette version.
### Ajouté
- **Serveur** (`server/`, Python + FastAPI + SQLite). Il porte désormais la recherche dans les
catalogues, le guet des morceaux sur les radios, l'enregistrement des directs et la file de
téléchargement. Une interface web permet de le piloter depuis un navigateur : recherche, guets,
file et bibliothèque.
- **Recherche simultanée sur toutes les sources.** Les quatre catalogues sont interrogés en
parallèle et les résultats fusionnés, chacun étiqueté de son origine, les plus légers en tête.
Un catalogue en panne n'empêche pas les autres de répondre.
- **Balayage radio continu.** Un tour enchaîne sur le suivant au lieu d'attendre trois minutes :
un morceau guetté a été capté en moins de vingt-cinq secondes à la mesure. Une sonde ne lit que
le premier bloc de métadonnées puis referme, ce qui rend la permanence tenable là où garder
quarante flux ouverts coûterait plusieurs mégabits par seconde.
- **Synchronisation client/serveur.** Le mobile demande ce qui a changé depuis son curseur,
télécharge les fichiers prêts et se rendort. Toutes les six heures, en Wi-Fi non facturé et
batterie suffisante.
- **Réglages en sous-onglets** sur le mobile : Connexion, Synchronisation, Application.
- Cibles `make server-*` : environnement, lancement, service systemd, jeton, journal.
### Changé
- **L'application Android devient un client de synchronisation.** Recherche, catalogues, radio,
guets et enregistrement quittent le téléphone : vingt fichiers supprimés. Restent la
bibliothèque, la lecture, les playlists, le hors-ligne et les réglages.
- L'onglet Sources devient Réglages.
### Corrigé
- Le jeton du serveur était régénéré à chaque démarrage : il aurait fallu reconfigurer le mobile
après le moindre redémarrage. Il est désormais conservé dans `data/token`, en lecture seule pour
son propriétaire.
- Wikimedia Commons répondait 403 : sa politique refuse les agents génériques. L'agent annonce
maintenant le projet et son dépôt — 28 résultats là où il n'y en avait aucun. L'erreur était
masquée par la fusion des sources, et n'est apparue qu'en interrogeant la source seule.
- `NOXELY_DATA` pointait par défaut sur `/var/lib/noxely`, inaccessible au compte qui lance
`make server-run` : le défaut devient `./data`, et l'unité systemd crée elle-même son dossier
d'état. Un dossier inutilisable donne désormais une phrase, plus une trace Python.
- La lecture des métadonnées ICY n'itérait rien côté serveur : `iter_bytes` au lieu de
`aiter_bytes` sur un client asynchrone. Trente-six stations écoutées, zéro titre lu.
- Une coupure de l'annuaire Radio Browser faisait échouer tout le balayage : une seconde tentative
est faite, et l'erreur renvoyée est lisible.
### Migration
Le mobile seul ne sert plus à rien : il faut installer le serveur (`make server-venv`, puis
`make server-install`), relever son jeton (`make server-token`) et le saisir dans Réglages ▸
Connexion. Consultée depuis la machine du serveur, l'interface web se remplit seule.
## [1.7.0] — 2026-09-13
### Ajouté
- **Guet sur l'ensemble des stations.** On nomme un morceau ou un artiste, sans désigner de
station : Noxely balaie les quarante stations les plus écoutées, quatre à la fois, et déclenche
l'enregistrement dès qu'une le diffuse. Un écran dédié sépare ce qui est attendu de ce qui a été
capté, avec le nombre de balayages et l'heure du dernier.
- **Veille en arrière-plan.** Deux mécanismes, parce qu'un seul ne suffit pas : une tâche
périodique tourne en permanence au quart d'heure — le minimum qu'autorise Android — et une
veille active, à enclencher, balaie toutes les trois minutes, écran éteint compris. Un morceau
durant trois à quatre minutes, la tâche périodique en manque forcément ; l'écran le dit au lieu
de le taire. La veille s'arrête d'elle-même quand plus rien n'est guetté.
- **Pochettes automatiques.** Les titres sans image en reçoivent une, cherchée sur leur nom via la
recherche publique d'iTunes, sans clé. Le nom est nettoyé au préalable : un enregistrement radio
traîne celui de sa station, qui brouillerait la requête.
- **Bouton d'actualisation** de l'écran Hors ligne : relance le scan de l'appareil et complète les
pochettes manquantes, par lots bornés pour ne pas marteler le service.
- L'écran de lecture affiche la provenance du morceau — nom de la playlist s'il en vient —, sa
source, sa taille et sa date.
### Corrigé
- Un morceau guetté n'était pas enregistré : le champ de saisie était vidé avant que la coroutine
n'en lise la valeur. Elle est désormais capturée avant l'effacement.
## [1.6.0] — 2026-09-13
### Changé
- **L'application s'appelle désormais Noxely.** Le nom affiché, l'identifiant d'application
(`fr.tuxgyver.noxely`), le paquet Kotlin, le dépôt et le dossier d'enregistrements
(`Music/Noxely`) suivent tous.
⚠️ **Android considère le nouvel identifiant comme une application distincte.** Une
installation en 1.5.0 ne se met donc pas à jour toute seule : il faut la désinstaller, puis
installer Noxely. Les enregistrements déjà rangés dans `Music/Cachette` ne sont pas perdus —
ils sont dans le stockage partagé, restent lisibles par tout lecteur, et le scan continue de
les écarter pour ne pas les afficher en double.
- Nouvelle icône. Le visuel fourni est détouré de son fond, décliné aux cinq densités et posé
sur une couleur échantillonnée dans l'image : sans cela, le masque du système aurait découpé
une seconde fois un badge qui l'est déjà, en laissant du blanc sur les bords.
### Ajouté
- Page « À propos », accessible depuis l'écran Sources : ce que fait l'application, ce qu'elle
garantit, avec quoi elle est construite, ce qui a changé et qui en répond. La version est lue
du manifeste et le journal du CHANGELOG du dépôt, recopié à la compilation — l'un et l'autre
ne peuvent donc pas diverger de la réalité.
- La pastille de licence signale en rouge qu'aucune licence n'est déclarée dans le dépôt, plutôt
que d'en afficher une par défaut.
## [1.5.0] — 2026-09-13
### Ajouté
- **Titre en cours par station.** Aucun annuaire ne l'expose : le morceau diffusé est lu dans le
flux lui-même. Les douze premières stations affichées sont sondées quatre à la fois, et le
résultat conservé — au-delà, le nombre de connexions ne se justifierait plus. Les stations qui
n'annoncent rien gardent leur description.
- **Guet d'un titre.** On indique un morceau ou un artiste, et l'enregistrement se déclenche dès
que la station l'annonce, puis s'arrête à la fin du morceau. Le flux est lu sans être écrit
pendant l'attente. Une station sans métadonnées refuse la programmation plutôt que d'attendre
indéfiniment.
- **Catalogue Underground.** Restreint aux collections `netlabels` et `freemusicarchive`, où tout
est publié sous licence libre par les artistes : environ 94 000 morceaux indépendants, que la
recherche généraliste noyait.
- **Suppression individuelle d'un enregistrement** depuis l'écran Hors ligne : fichier, entrée
MediaStore et référence en bibliothèque sont retirés ensemble.
### Modifié
- Les enregistrements sont désormais écrits dans `Music/Noxely` et déclarés dans MediaStore
(Android 10 et plus) : ils deviennent visibles des autres lecteurs et survivent à la
désinstallation. Le scan local ignore ce dossier, faute de quoi chaque enregistrement
apparaîtrait deux fois.
- Le nom de fichier porte le titre du morceau. En publiant le fichier, MediaStore le relit et
réécrit le champ `TITLE` depuis ce nom : l'y inscrire directement ne survivait pas.
## [1.4.0] — 2026-09-13
### Ajouté
- Titrage automatique des enregistrements radio. Le service demande désormais les métadonnées
ICY, ce qui fait annoncer par la station le morceau diffusé : l'enregistrement prend son nom,
la station passe en sous-titre, et le titre en cours s'affiche pendant la capture comme dans
la notification. Ces octets de métadonnées sont retirés avant écriture — laissés dans le
fichier, ils le rendraient illisible. Les stations qui n'en diffusent pas gardent le nom
« Station — date ».
### Corrigé
- Les enregistrements radio n'apparaissaient pas dans l'onglet « Hors ligne », qui ne listait que
ce qui porte un état de téléchargement. L'écran annonçait donc un nombre d'éléments disponibles
sans réseau en omettant précisément ceux qui l'étaient déjà. La taille affichée additionne
maintenant le cache et les enregistrements, et « Tout libérer » précise qu'il ne les touche pas.
- Les titres comportant une apostrophe étaient tronqués à la première rencontrée : « Ain't That a
Kick in the Head » devenait « Ain ». La valeur est lue jusqu'à la fin du champ ICY.
## [1.3.0] — 2026-09-13
### Ajouté
- **Radio.** Les stations les plus écoutées via l'annuaire communautaire Radio Browser, avec
filtres par genre et recherche par nom. Chaque station s'écoute en direct, ou s'enregistre :
un service de premier plan copie le flux dans un fichier jusqu'à l'arrêt demandé, et le verse
dans la bibliothèque — déjà hors connexion, sans rien à télécharger ensuite.
- Relance automatique des téléchargements en échec, après une pause croissante de 5, 15 puis
45 secondes. Une relance manuelle repart d'un compteur neuf.
### Notes
- Les flux HLS sont écartés de la liste des stations : ils se lisent, mais ne s'enregistrent pas
par copie d'octets, et un bouton qui échouerait vaudrait moins que pas de bouton.
- La relance et la reprise sur coupure réseau sont deux mécanismes distincts, et c'est voulu :
sans réseau, Media3 met le téléchargement en attente et le reprend de lui-même ; la relance,
elle, ne traite que les vrais échecs serveur.
- Le repli automatique vers une autre source n'a pas été retenu : rien ne garantit qu'un même
titre trouvé sur deux catalogues soit le même enregistrement, et l'application téléchargerait
silencieusement autre chose que ce qui a été choisi.
## [1.2.0] — 2026-09-13
### Ajouté
- Écran de choix des pistes. Un album ou un livre n'est plus une boîte noire : ses pistes sont
listées avec leur durée et leur taille, le total est annoncé, et le bouton dit exactement ce
qu'on s'apprête à télécharger (« Garder 4,2 Mo »). Les variantes d'un même morceau sont
regroupées — autant de lignes que d'œuvres, pas que de formats.
- Écoute en ligne avant téléchargement : un appui sur une piste la joue en streaming sans rien
mettre en cache.
- Playlists : listes nommées, ajout par appui long sur un média ou depuis l'écran de lecture,
lecture enchaînée, suppression piste par piste.
- Contrôles de lecture complétés : arrêt, saut de 15 secondes en avant et en arrière.
- Filtrage par langue des catalogues (français, anglais, allemand, espagnol, italien, néerlandais).
- Nouvelle source libre : **Wikimedia Commons**, pour les enregistrements classiques et les
archives sonores du domaine public.
### Corrigé
- Le filtre de langue de LibriVox ne pouvait pas fonctionner côté serveur : l'API accepte le
paramètre `language` puis l'ignore (`language=French` seul renvoie des livres anglais). Le tri
se fait désormais sur le champ `language` de chaque livre.
- Délais réseau ajustés d'après la latence mesurée des services : LibriVox répond en 14 à
16 secondes quelle que soit la taille demandée, ce qui faisait expirer les requêtes parallèles.
### Notes
- Deux catalogues ont été évalués puis écartés sur mesure plutôt que sur principe : **Openverse**
refuse désormais l'accès anonyme (401 sur huit requêtes sur huit) et **ccMixter** exige un
en-tête `Referer` que Media3 ne permet pas de poser par téléchargement.
## [1.1.0] — 2026-09-11
### Ajouté
- Mise à jour intégrée : Noxely surveille les releases du dépôt, télécharge l'APK en Wi-Fi
et propose l'installation. Vérification quotidienne en tâche de fond, et à la demande depuis
l'écran Sources, qui affiche aussi la version installée.
- La taille approximative de chaque résultat Internet Archive est affichée avant sélection : un
élément de 500 Mo ne se laisse plus confondre avec une chanson.
### Corrigé
- Recherche LibriVox qui ne renvoyait rien. L'API cherche les titres en correspondance exacte
sauf si la requête est préfixée par `^`, et les auteurs sur le seul nom de famille : « Jules
Verne » n'atteignait donc ni l'un ni l'autre. Les trois critères sont désormais interrogés en
parallèle et dédoublonnés, et un « aucun résultat » (HTTP 404) n'est plus traité comme une panne.
- Téléchargements Internet Archive qui échouaient ou n'aboutissaient pas. Trois causes distinctes :
les éléments en accès restreint répondaient 401 et sont maintenant écartés dès la recherche ;
seuls les fichiers `.mp3` et `.mp4` étaient acceptés, ce qui excluait des éléments ne proposant
que du `.m4a` ou de l'`.ogg` ; et le fichier retenu était le premier trouvé, souvent l'original
non compressé — c'est désormais le plus petit dérivé, soit 9 Mo au lieu de 30 sur un cas mesuré.
## [1.0.0] — 2026-09-11
### Ajouté
- Lecture audio et vidéo en arrière-plan (Media3 `MediaSessionService`), avec notification
système, commandes casque et écran verrouillé.
- Mise en cache hors connexion explicite : téléchargement à la demande, reprise automatique
après coupure réseau ou redémarrage via WorkManager.
- Bibliothèque unifiée mêlant le contenu de l'appareil (MediaStore) et les médias importés.
- Sources : appareil, lien direct `http(s)`, flux RSS de podcast.
- Catalogues libres de droits intégrés : Internet Archive et LibriVox, sans compte ni clé d'API.
- Parcours d'une source avec sélection multiple et téléchargement en lot.
- Écran « Hors ligne » : taille du cache, progression, libération élément par élément ou en bloc.
- Interface Jetpack Compose Material 3, thème clair et sombre, palette de marque.