Un serveur musical pour mon salon
Aujourdâhui, on va mettre en place un serveur musical pilotable Ă distance en utilisant MPD. Il sera notamment capable de jouer de la musique stockĂ©e dessus ou des radios Internet. Il sera aussi capable de se comporter comme une enceinte Bluetooth.
On va parler de rĂ©cup de vieux matos, de Debian, MPD, PipeWire, Samba, dâagent Bluetooth, de systemd (-analyze
, -logind
), de Powertop et de vbetool.
Cet article au ton trĂšs « administration systĂšme » sâadresse Ă :
- des gens qui voudraient mettre en place un systĂšme plus ou moins similaire, mĂȘme pour faire autre chose dans le mĂȘme esprit (en mode tutoriel) ;
- des gens qui aiment les dĂ©tails techniques et voir les trucs cools quâon peut faire avec les logiciels libres ;
- toute autre personne curieuse pour dâautres raisons.
Il est probablement trop technique pour quelquâun qui ne manipule pas la ligne de commande, qui pourra peut-ĂȘtre malgrĂ© tout, avec suffisamment de motivation, se laisser porter par la dĂ©marche.
- lien ná” 1 : Debian
- lien ná” 2 : Using a Raspberry Pi as a Bluetooth speaker with PipeWire
- lien ná” 3 : Music Player Daemon
- lien ná” 4 : MPD Clients
- lien ná” 5 : M.A.L.P sur F-Droid
- lien ná” 6 : Cantata
- lien ná” 7 : Samba
- lien ná” 8 : Command-Line Methods for Turning Monitor on or off in Linux
- lien ná” 9 : How do I run a single command at startup using systemd?
- lien ná” 10 : Writing a systemd service to be executed at resume
- lien ná” 11 : How to manage wireless connections using iwd on Linux
- lien ná” 12 : How do I make Powertop changes permanent?
- lien ná” 13 : rsgain
- lien ná” 14 : Using MPD for ReplayGain
- lien ná” 15 : Guide: Getting Wireplumber to work without D-Bus
Sommaire
- Introduction
- Installation standard minimaliste de Debian
- Gains énergétiques potentiels
- MPD : Music Player Deamon
- Samba pour déposer les morceaux (et les playlists)
-
Récepteur Bluetooth
- Garder une session utilisateur active
- Installer PipeWire et les choses nécessaires
- Installer un agent Bluetooth qui accepte toutes les connexions audio sans vérifications avec code
- Adapter MPD (et Samba) pour utiliser PipeWire
- Permettre à PipeWire de configurer sa priorité
- Ăvitez les flux Wifi 2,4 GHz
- Note sur lâutilisation des ressources
- Conclusion et améliorations possibles
Introduction
Note de lecture : cette dĂ©pĂȘche est trĂšs dĂ©taillĂ©e, je vous conseille de passer les sections qui vous intĂ©ressent moins.
Motivation
Dans mon salon, jâai des petites enceintes toutes bĂȘtes qui sonnent plutĂŽt bien. Mettre de la musique implique de sâembĂȘter Ă brancher un ordinateur, sur lequel je suis le seul avoir le contrĂŽle. Ce serait bien dâavoir un systĂšme prĂȘt Ă lâemploi et que tout le monde peut contrĂŽler.
Objectifs
- Pas dâachat : on fait avec de la rĂ©cup
- Peu gourmand en énergie
- Silencieux (à part la musique, bien sûr)
- Facile Ă utiliser pour une personne non technique
- Pouvoir mettre de la musique sans que ça soit pénible, en utilisant ma bibliothÚque musicale locale, ou des radios internet
- Pouvoir laisser nâimporte qui se connecter en Bluetooth et lancer sa propre musique
Nous allons, ensemble, remplir ces objectifs. On va rentrer dans les dĂ©tails, qui peuvent ĂȘtre utiles dans dâautres applications, et parce que je sais que certaines personnes ici aiment ça, bande de geeks :-)
Matériel à disposition
- des enceintes parfaitement fonctionnelles mais sans fonctionnalité Bluetooth
- un appareil style netbook du dĂ©but des annĂ©es 2010 (dans mon cas, câest une vieille tablette Airis Kira Slimpad plus vraiment adaptĂ©e au web moderne, dotĂ©e dâun processeur Intel Atom un peu lent, dâun peu de stockage assez lent, dâun Wifi plutĂŽt lent, du Bluetooth, dâ1 Giga de mĂ©moire vive)
Note sur les interfĂ©rences Wifi et Bluetooth. Le Wifi de cette tablette est en 2,4 GHz, pareil que le Bluetooth. Tout Ă©change wifi cause des perturbations sur le Bluetooth et tout transfert intensif rend le Bluetooth inutilisable. Du grand classique. Un Wifi 5, 6 ou 7 aurait Ă©tĂ© apprĂ©ciable. Il serait possible dâutiliser une carte Wifi USB, mais je nâen ai pas donc on fera sans.
Ce quâon va faire dans les grandes lignes
- Installer une Debian minimale
- La configurer pour quâelle soit accessible par le rĂ©seau, la plus rapide et lĂ©gĂšre possible en utilisation mĂ©moire, en temps de dĂ©marrage et en consommation Ă©nergĂ©tique
- Installer et configurer MPD
- Installer et configurer Samba
- Configurer en mode « enceinte Bluetooth »
Installation standard minimaliste de Debian
Par souci de concision, on ne va pas dĂ©tailler lâinstallation de Debian, il existe dâautres ressources au besoin.
En résumé :
- Debian classique en 32 bits (ça consomme moins de mémoire que du 64 bits)
- jâai laissĂ© lâinstallateur faire le partitionnement (une partition principale en ext4, et une partition swap de 1G)
- jâai ajoutĂ© lâoption noatime sur la partition principale pour Ă©viter dâĂ©crire inutilement lors des accĂšs, ce qui use le SSD et ralentit le systĂšme (dâautant que le SSD est lent)
- lors de lâĂ©tape Tasksel, choisir console, serveur ssh et utilitaires standard, et en particulier pas dâenvironnement de bureau
- on installe sudo et on ajoute lâutilisateur au groupe sudo, ou alors on se donne accĂšs Ă root en ssh avec une clĂ© SSH
- on installe iwd (le remplaçant moderne de
wpa_supplicant
, supposĂ© plus performant et plus stable permettant Ă©galement de se passer de NetworkManager assez facilement) et on connecte lâappareil en wifi avec - on identifie et dĂ©sactive ou on dĂ©sinstalle le superflu avec
systemd-analyze critical-chain
etsystemd-analyze blame
(typiquement, si vous avez installĂ© NetworkManager, ModemManager a peut-ĂȘtre Ă©tĂ© installĂ© alors que vous nâavez pas de modem Ă gĂ©rer)
- on peut configurer le menu de Grub pour moins attendre au démarrage
Note : sur cette tablette, lâinstallateur Debian nâarrive pas Ă se connecter en Wifi, jâai donc utilisĂ© la version DVD (le premier suffit).
Gains énergétiques potentiels
Ăteindre lâĂ©cran
LâĂ©cran est potentiellement une des plus grosses sources de consommation Ă©lectrique. On nâen a pas besoin, donc on va lâĂ©teindre au dĂ©marrage et Ă la sortie de veille.
Pour cela, on va installer vbetool (sources : outils pour Ă©teindre lâĂ©cran, lancer une commande au dĂ©marrage, lancer une commande aprĂšs la veille):
sudo apt install vbetool
cat << EOF | sudo tee /etc/systemd/system/screenoff.service
[Unit]
Description=Screen off
After=suspend.target
[Service]
ExecStart=vbetool dpms off
[Install]
WantedBy=multi-user.target suspend.target
EOF
Attention : ça peut compliquer grandement lâusage de lâappareil, on peut vouloir appliquer un dĂ©lai avant extinction pour se faciliter la vie.
Powertop pour améliorer la consommation électrique
Powertop permet de voir ce qui utilise le CPU et les diverses ressources, et dâajuster un peu les paramĂštres de mise en veille de diffĂ©rents pĂ©riphĂ©riques.
On va lâinstaller :
sudo apt install powertop
Ensuite, ça peut ĂȘtre cool de lancer lâoutil pour constater un peu ce qui tourne et consomme des ressources, de se dĂ©placer dans les onglets, et de tenter des trucs dans lâonglet « Tunables » :
sudo powertop
Si passer tout Ă Good
ne cause pas de problĂšme dâinstabilitĂ© Ă©vidente, alors on peut appliquer la configuration de Powertop Ă chaque dĂ©marrage (source) :
cat << EOF | sudo tee /etc/systemd/system/powertop.service
[Unit]
Description=PowerTOP auto tune
[Service]
Type=oneshot
Environment="TERM=dumb"
RemainAfterExit=true
ExecStart=/usr/sbin/powertop --auto-tune
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable powertop.service
Sinon, il y a des solutions mentionnées dans la source pour désactiver certains changements (si vous observez des dysfonctionnements avec certains périphériques par exemple, et notamment si vous avez des problÚmes de Wifi ou Bluetooth)
Perso, je sais que sur cette tablette, passer tout Ă Good
fait (faisait il y a 10 ans en tout cas) quâaprĂšs un dĂ©lai la premiĂšre frappe sur le clavier ou le premier clic de la souris Ă©tait ignorĂ©, et aussi Ă©tait nĂ©cessaire pour rĂ©veiller lâUSB â clairement je mâen fiche ici, mais si votre wifi ou votre Bluetooth est en USB et que les paramĂštres causent une extinction aprĂšs un dĂ©lai, clairement ce nâest pas bon).
Bonus : Configurer le bouton power pour mettre en veille
Sur ma tablette, un appui court sur le bouton power Ă©teint la tablette (et ensuite on la rallume en appuyant 3 longues secondes). Si on souhaite quâun appui court mette en veille lâappareil et un appui long lâĂ©teigne, comme ça on fait un compromis Ă©nergĂ©tique supposĂ©ment raisonnable pour rendre lâensemble un poil plus pratique, câest facile avec systemd.
Ajoutez ces deux lignes au fichier /etc/systemd/logind.conf
:
HandlePowerKey=suspend
HandlePowerKeyLongPress=poweroff
Rechargez les paramĂštres :
sudo systemctl restart systemd-logind
MPD : Music Player Deamon
Ok, passons au cĆur du sujet : mpd.
Késako
Simplement, câest un lecteur de musique pilotable Ă distance qui est capable de :
- lire de la musique que vous mettez dans son dossier de travail ;
- lire des playlists que vous mettez dans son dossier de travail ;
- lire des flux radio, qui sont par exemple définis dans des playlists.
Entre autres.
Certains clients MPD, comme Cantata (une application Qt5 plus ou moins abandonnĂ©e mais encore dans les dĂ©pĂŽts), sont mĂȘme capables de lire de la musique sur votre serveur MPD que vous avez localement sur votre ordinateur, ou de gĂ©rer les playlists. Ăa rend dâailleurs la constitution de playlists vaguement confortable. Vous nâavez pas besoin dâĂ©crire des playlists M3U Ă la main, quoi.
Les avantages sont multiples :
- câest mĂ©ga lĂ©ger, une machine Ă©puisĂ©e peut faire tourner MPD Ă lâaise
- si vous lisez la musique stockĂ©e sur le serveur, le rĂ©seau nâest pas engorgĂ©
- on peut ĂȘtre plusieurs Ă contrĂŽler la musique, ce nâest pas une personne qui contrĂŽle tout, et on peut le faire depuis le canapĂ©
- il existe toute une flopĂ©e de clients, il y en a pour tous les goĂ»ts pourvu que vous aimiez les logiciels abandonnĂ©s ou en ligne de commande / en ncurses (ouais, câest quand mĂȘme un problĂšme que jâidentifie et qui a largement retardĂ© mon adoption de MPD)
- les gens non techniques apprécieront les applications mobiles telles que M.A.L.P pour gérer la musique et le volume sonore.
Câest parti pour lâinstallation
sudo apt install mpd
On va modifier sa configuration :
sudo nano /etc/mpd.conf
On peut laisser les paramÚtres par défaut suivants :
music_directory "/var/lib/mpd/music"
playlist_directory "/var/lib/mpd/playlists"
Vous lâaurez compris, câest lĂ oĂč on stocke les musiques et les playlists. Dans la section suivante, on verra comment rendre le dĂ©pĂŽt de morceaux simple et convivial.
On va laisser la plupart des autres paramÚtres par défaut.
On va changer bind_to_address
, qui est par défaut à localhost
, mais on veut que nâimporte quel appareil sur le rĂ©seau soit capable de s'y connecter. On va aussi explicitement mettre le port Ă la valeur par dĂ©faut (ce nâest probablement pas nĂ©cessaire, mais câest ce que jâai fait) :
bind_to_address "0.0.0.0"
port "6600"
On veut aussi que quand des fichiers sont changés dans les dossiers music
et playlists
, mpd se mette Ă jour tout seul pour ne pas avoir Ă le baby-sitter :
auto_update "yes"
Jâai tentĂ© dâactiver zeroconf pour que les clients MPD puissent le trouver tout seul :
zeroconf_enabled "yes"
zeroconf_name "Music Player @ %h"
Mais en vrai, je nâai pas rĂ©ussi Ă faire fonctionner ça. En tout cas, un prĂ©requis est dâavoir installĂ© et activĂ© avahi-daemon
, on verra ça plus tard dans la partie Samba du coup.
Vous aurez peut-ĂȘtre envie de mettre un mot de passe voire de changer les permissions par dĂ©faut en dĂ©commentant et adaptant les paramĂštres suivants, mais câest optionnel :
#password "password@read,add,control,admin"
#default_permissions "read,add,control,admin"
Ensuite, la partie critique, la sortie audio. Pour lâinstant, on va dire Ă mpd
dâutiliser Alsa directement. Câest le plus direct et le plus lĂ©ger (on passera Ă PipeWire plus tard, pour gĂ©rer lâaspect rĂ©cepteur Bluetooth)
audio_output {
type "alsa"
name "My ALSA Device"
device "hw:0,0" # optional
mixer_type "hardware" # optional
# mixer_device "default" # optional
mixer_control "Master" # optional
mixer_index "0" # optional
}
Pour une de mes installations, jâai commentĂ© mixer_device
parce que ce nâest manifestement pas la bonne valeur chez moi, et que ça marche bien sans.
Vous pouvez vous passer des autres valeurs optionnelles, mais vous nâaurez pas le contrĂŽle du volume sonore depuis les clients MPD si vous faites ça. Vous allez donc devoir trouver les bonnes valeurs pour les paramĂštres mixer_*
, et pour device
. ainsi que mixer_control
et mixer_index
.
Quelques indices :
-
hw:0,0
est probablement la bonne valeur pourdevice
, et0
pourmixer_index
aussi. Vous pouvez lister vos cartes son avecaplay -L
. Vous aurez peut-ĂȘtre besoin dâinstaller le paquetalsa-utils
. - la valeur de
mixer_control
est le nom du contrĂŽle que vous utiliserez pour changer le volume dansalsamixer
, du paquetalsamixergui
que vous aurez probablement besoin dâinstaller.
Si vous galérez trop avec les valeurs de mixer-*
, vous pouvez simplement utiliser mixer_type "software"
, câest moins propre mais ça devrait faire le taf. Et sinon, vous pouvez toujours sortir lâartillerie lourde et passer directement Ă PipeWire.
Pour appliquer vos modifications :
systemctl enable --now mpd # Ă partir de Debian Trixie, mpd nâest plus activĂ© par dĂ©faut au niveau du systĂšme
systemctl restart mpd # Si MPD tournait dĂ©jĂ
Vous pouvez déboguer vos changements avec la commande suivante, qui suit les logs en temps réel :
journalctl -fu mpd
Vous avez plusieurs options pour essayer de lire des choses avec mpd :
- installer lâapplication M.A.L.P sur votre tĂ©lĂ©phone Android, ou une autre application cliente MPD, et ajouter un profil avec la bonne adresse, le bon port et le bon mot de passe ;
- installer un client comme Cantata sur votre ordinateur, avec la bonne adresse, le bon port et le bon mot de passe ;
- installer
mpc
directement sur le serveur. Normalementmpc play
permet de lancer la lecture.
Moi, jâai testĂ© avec une webradio dans une playlist (/var/lib/mpd/playlists/radio-paradise-main-mix.m3u
avec le contenu http://stream.radioparadise.com/ogg-192m
), mais on peut aussi évidemment placer un morceau dans /var/lib/mpd/music/
.
ReplayGain
Le niveau sonore de mes morceaux nâest pas homogĂšne, donc il faut sans cesse adapter le volume dâun morceau Ă lâautre. Câest pĂ©nible, voire inutilisable en lâĂ©tat. Une solution pour ça est replay gain : on analyse et on enregistre le niveau sonore dâune piste dans ses mĂ©tadonnĂ©es.
Il existe plein dâoutils pour faire ça, dont https://github.com/complexlogic/rsgain
On peut le faire avant dâenvoyer les fichiers sur lâappareil. Pour ma part, je lâai fait sur la tablette, et il nâexiste pas de paquet Debian 32 bits, donc je lâai compilĂ© :
sudo apt install cmake build-essential pkd-config git libavcodec-dev libavformat-dev libtag1-dev libebur128 libinih-dev libfmt-dev
git clone --depth=1 https://github.com/complexlogic/rsgain
cd rsgain
mkdir build
cd build
cmake ..
make -j2
sudo make install
Il faudra s'assurer que les morceaux au format Opus sont étiquetés avec le tag R128_TRACK_GAIN
et pas REPLAYGAIN_TRACK_GAIN
, parce que c'est ce que MPD sâattend Ă avoir. Pour ça, on va convaincre rsgain de suivre les standards (que certains lecteurs de musiques ne comprennent pas) en crĂ©ant un preset qui contient :
[Opus]
OpusMode=s
Mes morceaux ne sont pas organisĂ©s par albums, donc je dĂ©sactive lâanalyse par album. Je vais donc partir du preset no_album :
mkdir -p ~/.config/rsgain/presets; cat << EOF > ~/.config/rsgain/presets/no_album_standard_opus.ini
[Global]
TagMode=i
Album=false
TargetLoudness=-18
ClipMode=p
MaxPeakLevel=0.0
TruePeak=false
Lowercase=false
ID3v2Version=keep
PreserveMtimes=false
DualMono=false
OpusMode=s
EOF
Ensuite, on peut le rsgain sur le dossier de musiques avec ce preset. Mes morceaux ne sont pas organisĂ©s par albums, donc je dĂ©sactive lâanalyse par album.
rsgain easy -p no_album_standard_opus -m MAX /var/lib/mpd/music
Note : l'option --skip-existing
permet d'ignorer les fichiers déjà taggés :
rsgain easy --skip-existing -p no_album_standard_opus -m MAX /var/lib/mpd/music
Avec cette option, on peut exĂ©cuter cette tĂąche rĂ©guliĂšrement, par exemple dans un cron, pour calculer le ReplayGain pour les nouveaux fichiers. Pour la premiĂšre exĂ©cution, il vaut certainement mieux ne pas lâutiliser, sinon, si vous aviez dĂ©jĂ des fichiers qui avaient l'information, il se peut que le rĂ©sultat ne soit pas uniforme.
Il faut dire Ă MPD dâutiliser le ReplayGain dans /etc/mpd.conf
:
replaygain "track"
Vous aurez peut-ĂȘtre besoin de jouer avec les autres paramĂštres liĂ©s au volume et au ReplayGain.
Voici les miens :
# Ce paramÚtre définit la pré-amplification à appliquer pour les morceaux qui ont l'information du ReplayGain
replaygain_preamp "0"
# Ce paramÚtre définit la pré-amplification à appliquer pour les morceaux qui ne l'ont pas
replaygain_missing_preamp "0"
# Faut-il interdire à MPD de dépasser le niveau original d'amplification en appliquant le ReplayGain?
replaygain_limit "no"
# Faut-il permettre Ă MPD d'ajuster le volume pendant la lecture pour normaliser ?
volume_normalization "no"
Un autre paramĂštre quâon peut rĂ©gler, c'est la maniĂšre dont MPD rĂšgle le volume dynamiquement pour ReplayGain. Dans votre bloc audio_output
, vous pouvez ajouter replay_gain_handler
et la valeur "software"
(c'est la valeur par défaut) ou "mixer"
. En théorique, les traitements software dégradent le son, mais en pratique, avec "mixer"
, je tombe sur ce bug qui met le volume Ă 100% aprĂšs chaque changement de piste.
Note : je ne suis pas encore convaincu dâavoir rĂ©ussi Ă trouver les rĂ©glages parfaits, nâhĂ©sitez pas Ă expĂ©rimenter.
Les clients MPD
Ă ce stade, vous devriez avoir un serveur MPD fonctionnel et configurĂ©. Si applicable, vous pouvez commencer Ă suggĂ©rer aux gens de votre foyer dâinstaller lâapplication M.A.L.P sur leur appareil Android ; elle est libre et disponible sur F-Droid et sur le Play Store. Avec un peu de chance, votre enthousiasme Ă©tait communicatif et câest eux qui vous demanderont :-)
Pour les autres types dâappareils, vous allez devoir faire vos recherches vous-mĂȘme je nâai pas Ă©tudiĂ© les options sous Windows, Mac ou iPhone, mais il y en a. Pour Linux, jâai essayĂ© Cantata. Il me convient, si ce nâest quâil a lâair un peu abandonnĂ©, et il a une interface certes conviviale, mais quand mĂȘme un peu brute. Il existe des widgets qui sâintĂšgrent aux diffĂ©rents environnements de bureaux pour les diffĂ©rents systĂšmes dâexploitation, je nâai pas explorĂ©. Le site de MPD propose une liste de clients, et le wiki de Arch aussi.
Samba pour déposer les morceaux (et les playlists)
DĂ©poser des morceaux, vous allez probablement le faire depuis un ordinateur, et Ă peu prĂšs nâimporte quel systĂšme dâexploitation est capable dâaller chercher un dossier SMB en rĂ©seau, alors je vous propose de configurer un serveur Samba. Ăa a le bon goĂ»t dâĂȘtre trĂšs lĂ©ger, trĂšs simple Ă faire et de fonctionner depuis nâimporte quel OS. Allons-y, et tant quâĂ faire, on va aussi installer Avahi, qui permettra aux ordinateurs sous Linux et Mac de dĂ©couvrir les dossiers partagĂ©s tous seuls :
sudo apt install samba avahi-daemon
On va partager nos dossiers music
et playlists
au monde entier en lecture-écriture (YOLO). On édite /etc/samba/smb.conf
:
[Musique]
path=/var/lib/mpd/music
read only=no
writable=yes
comment=Fichiers musique MPD
guest ok = yes
force group = audio
force user = mpd
browsable = yes
public = yes
create mask = 0644
directory mask = 0755
[Playlists]
path=/var/lib/mpd/playlists
read only=no
writable=yes
comment=Listes de lecture MPD
guest ok = yes
force group = audio
force user = mpd
browsable = yes
public = yes
create mask = 0644
directory mask = 0755
Je ne maitrise pas particuliĂšrement Samba et il y a peut-ĂȘtre des options superflues, mais globalement lâesprit câest :
- nâimporte qui doit pouvoir accĂ©der Ă ces deux en lecture et en Ă©criture depuis le rĂ©seau. En particulier, la crĂ©ation de dossiers doit marcher
- MPD doit pouvoir lire ce quâon a Ă©crit dans ces dossiers
- les fichiers et dossiers doivent avoir des permissions sensées
Bien sĂ»r, on peut vouloir restreindre lâaccĂšs Ă certains utilisateurs et/ou avec un mot de passe. Je vous laisse creuser.
AprÚs un redémarrage de Samba :
sudo systemctl restart samba
Avec un peu de chance, dans lâonglet «âŻRĂ©seauâŻÂ» de votre gestionnaire de fichier, dans la section «âŻPartages SMBâŻÂ», votre appareil apparait. Sinon, vous devriez pouvoir y accĂ©der avec smb://HOST/
avec Dolphin et probablement Nautilus, probablement \\HOST
sous Windows.
Alternatives possibles Ă Samba
- Si on a un NAS, monter un dossier sur le serveur MPD, voire installer MPD sur le serveur de stockage, ou avoir une tùche chron qui fait un rsync bien placé
- Mettre en place une synchronisation avec Nextcloud ou Syncthing, et faire pointer MPD vers le bon dossier, ou ajouter le dossier de MPD comme dossier de stockage externe Ă Nextcloud par exemple
- SFTP
- NFS
- FTP (mais les autres options sont probablement meilleures)
Récepteur Bluetooth
Ce nâest bien sĂ»r pas nĂ©cessaire si vous ĂȘtes parfaitement satisfait·e avec MPD, mais si vous voulez que votre appareil soit en plus capable de se comporter comme une enceinte Bluetooth, vous ĂȘtes au bon endroit.
Les difficultĂ©s quâon va rĂ©soudre sont les suivantes :
- pour lâinstant, MPD accĂšde au son directement avec ALSA, et en gĂ©nĂ©ral on ne peut pas ĂȘtre plusieurs sur ALSA. En tout cas, et mĂȘme sâil a lâair possible de faire fonctionner Bluetooth et ALSA ensemble, ça nâa pas lâair dâĂȘtre terriblement simple ou mĂȘme stable. Donc on va utiliser PipeWire. On aurait pu utiliser PulseAudio, mais PipeWire le remplace, et fonctionne gĂ©nĂ©ralement mieux.
- PipeWire, câest pensĂ© pour ĂȘtre lancĂ© dans une session graphique dâun utilisateur, mais nous, on a un serveur headless. Il va falloir faire en sorte de lancer une session utilisateur au dĂ©marrage sans interaction, et que cette session ne soit pas tuĂ©e.
- mpd tourne avec son utilisateur, PipeWire avec son utilisateur, et aprĂšs sâĂȘtre rendu compte quâil faut que ça soit les mĂȘmes, faut aussi savoir comment, et le faire.
Lors de lâinstallation de Debian, on a dĂ©fini un utilisateur. On peut utiliser cet utilisateur. Sinon, on peut aussi en crĂ©er un pour ça, pensez bien Ă lâajouter aux groupes audio
et bluetooth
.
Garder une session utilisateur active
On va démarrer une session utilisateur au boot :
sudo loginctl enable-linger user # remplacer user par le nom dâutilisateur
On va sâassurer que les processus de cette session ne sont pas tuĂ©s au moment oĂč on quitte une session (par exemple quand on quitte une session ssh) : dans le fichier /etc/systemd/logind.conf
, décommentez la ligne KillExcludeUsers
et ajouter le nom dâutilisateur aprĂšs le =
. Vous deviez avoir
KillExcludeUsers=user
oĂč user
est le nom dâutilisateur.
On peut maintenant recharger ces paramĂštres :
sudo systemctl restart systemd-logind
Installer PipeWire et les choses nécessaires
Ă ce stade, MPD bloque probablement lâutilisation du son parce quâil sây connecte via ALSA. On va le stopper.
sudo systemctl stop mpd
PipeWire et WirePlumber vont dorénavant gérer le son, et libspa-0.2-bluetooth
permet au dĂ©mon qui gĂšre le Bluetooth (Bluez) de sâinter-connecter Ă PipeWire pour le Bluetooth Audio.
sudo apt install wireplumber pipewire libspa-0.2-bluetooth
En tant que votre utilisateur (nommé user
dans les commandes prĂ©cĂ©dentes) (câest important), activez PipeWire au dĂ©marrage et lancez-le :
systemctl --user enable --now pipewire wireplumber
Notez que pipewire-pulse
nâest pas nĂ©cessaire, dâailleurs vous pouvez le supprimer ou le dĂ©sactiver en toute sĂ©curitĂ© sâil a Ă©tĂ© installĂ©.
Installer un agent Bluetooth qui accepte toutes les connexions audio sans vérifications avec code
Normalement, accepter les connexions Bluetooth se fait Ă lâaide dâun agent Bluetooth :
- qui tourne dans votre session graphique : câest gĂ©rĂ© par votre environnement de bureau, ou une application comme
bluetooth-applet
(est-ce que ça existe encore ?) que vous lancez. LĂ , Ă©videmment, on nâa pas de session graphique, et pour lâinstant on nâa pas dâagent Bluetooth qui tourne. - En ligne de commande, avec un outil comme
bluetoothctl
. Je vous invite Ă essayer. Vous pouvez lancer des commandes commepairable on
,discoverable on
,scan on
, et essayer de vous connecter avec un autre appareil. AprÚs vos tests, vous pouvez tout recommencer en faisant oublier les appareils des deux cÎtés.
Ăvidemment, on ne va pas se connecter en ssh pour lancer bluetoothctl
Ă chaque fois quâon veut se connecter en Bluetooth. On va mettre en place un agent qui dĂ©marre automatiquement et qui a un comportement similaire Ă un casque ou des enceintes Bluetooth : qui accepte toutes les connexions Bluetooth audio. Pour ça, on va utiliser un script Python partagĂ© par Collabora sous Licence LGPL 2.1+ qui fait ça trĂšs bien et quâon va lancer au dĂ©marrage.
Bien sĂ»r, ça veut dire que vos voisins peuvent sâamuser Ă jouer des trucs chez vous, ou mĂȘme se connecter fortuitement en choisissant la mauvaise entrĂ©e.
Ce script a une dĂ©pendance, quâon va installer :
sudo apt install python3-dbus
On va placer ce script dans speaker-agent.py
:
#!/usr/bin/python3
# SPDX-License-Identifier: LGPL-2.1-or-later
import dbus
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib
BUS_NAME = 'org.bluez'
AGENT_INTERFACE = 'org.bluez.Agent1'
AGENT_PATH = "/speaker/agent"
A2DP = '0000110d-0000-1000-8000-00805f9b34fb'
AVRCP = '0000110e-0000-1000-8000-00805f9b34fb'
bus = None
class Rejected(dbus.DBusException):
_dbus_error_name = "org.bluez.Error.Rejected"
class Agent(dbus.service.Object):
exit_on_release = True
def set_exit_on_release(self, exit_on_release):
self.exit_on_release = exit_on_release
@dbus.service.method(AGENT_INTERFACE,
in_signature="", out_signature="")
def Release(self):
print("Release")
if self.exit_on_release:
mainloop.quit()
@dbus.service.method(AGENT_INTERFACE,
in_signature="os", out_signature="")
def AuthorizeService(self, device, uuid):
# Always authorize A2DP and AVRCP connection
if uuid in [A2DP, AVRCP]:
print("AuthorizeService (%s, %s)" % (device, uuid))
return
else:
print("Service rejected (%s, %s)" % (device, uuid))
raise Rejected("Connection rejected by user")
@dbus.service.method(AGENT_INTERFACE,
in_signature="", out_signature="")
def Cancel(self):
print("Cancel")
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
agent = Agent(bus, AGENT_PATH)
mainloop = GLib.MainLoop()
# By default Bluetooth adapter is not discoverable and there's
# a 3 min timeout
# Set it as always discoverable
adapter = dbus.Interface(bus.get_object(BUS_NAME, "/org/bluez/hci0"),
"org.freedesktop.DBus.Properties")
adapter.Set("org.bluez.Adapter1", "DiscoverableTimeout", dbus.UInt32(0))
adapter.Set("org.bluez.Adapter1", "Discoverable", True)
print("RPi speaker discoverable")
# As the RPi speaker will not have any interface, create a pairing
# agent with NoInputNoOutput capability
obj = bus.get_object(BUS_NAME, "/org/bluez")
manager = dbus.Interface(obj, "org.bluez.AgentManager1")
manager.RegisterAgent(AGENT_PATH, "NoInputNoOutput")
print("Agent registered")
manager.RequestDefaultAgent(AGENT_PATH)
mainloop.run()
Le script mentionne le Raspberry Pi, mais il nây a absolument rien de spĂ©cifique au Raspberry dedans, il est suffisamment gĂ©nĂ©rique.
On va lancer ce script au démarrage en créant le fichier ~/.config/systemd/user/speaker-agent.service
[Unit]
Description=Bluetooth speaker agent
[Service]
ExecStart=python3 speaker-agent.py
[Install]
WantedBy=default.target
Et en lâactivant (--now
le lance tout de suite) :
systemctl --user enable --now speaker-agent.service
Il faudra aussi mettre JustWorksRepairing = always
dans /etc/bluetooth/main.conf
pour permettre le re-appairage sans interaction. Bon lĂ jâavoue, je paraphrase largement ma source :-)
Ensuite, on va autoriser la connexion Bluetooth mĂȘme sans session active (en SSH par exemple) (source). Si on ne fait pas ça, la connexion Bluetooth nâest pas possible si lâutilisateur nâa pas une session active (les symptĂŽmes : on arrive Ă se connecter en Bluetooth que quand on est logguĂ© en SSH ou autre, et la connexion Bluetooth casse dĂšs quâon quitte la session).
mkdir -p ~/.config/wireplumber/bluetooth.lua.d
cat > ~/.config/wireplumber/bluetooth.lua.d/80-disable-logind.lua << EOF
-- Disable arbitration of user allowance of bluetooth via D-Bus user session
bluez_monitor.properties["with-logind"] = false
EOF
systemctl --user restart wireplumber
Adapter MPD (et Samba) pour utiliser PipeWire
Pour que MPD utilise PipeWire, il faut adapter :
- sa configuration pour quâil tourne avec le mĂȘme utilisateur
- sa configuration
audio_output
- les permissions dans
/var/lib/mpd
Dans /etc/mpd.conf
, changer la ligne user :
user "mpd"
Elle doit maintenant utiliser votre utilisateur :
user "user"
Commentez votre bloc audio_output
, on va maintenant utiliser PipeWire (je suppose quâon pourrait garder les deux et les clients MPD peuvent probablement permettre de choisir la sortie son, mais ça me parait complexifier lâutilisation pour un intĂ©rĂȘt pas clair, ce qui va contre nos objectifs) :
audio_output {
type "pipewire"
name "PipeWire Sound Server"
}
Maintenant, il est temps dâadapter les permissions dans /var/lib/mpd
. On va stopper Samba juste avant, et adapter sa configuration.
sudo systemctl stop mpd samba # si mpd tournait encore
sudo chown -rv user /var/lib/mpd
sudo systemctl start mpd
Note : MPD peut aussi ĂȘtre dĂ©marrĂ© dans une session utilisateur et Ă ce stade, câest ce quâil serait probablement le plus logique de faire, en bougeant /etc/mpd.conf
et le contenu de /var/lib/mpd
dans le dossier de notre utilisateur. Câest dâailleurs la maniĂšre privilĂ©giĂ©e de dĂ©marrer MPD Ă partir de Debian Trixie. Par simplicitĂ© et cohĂ©rence, et parce que cette section « RĂ©cepteur Bluetooth » est optionnelle mais que les manipulations pour lancer une session utilisateur au dĂ©marrage dĂ©crites dans cette section seraient nĂ©cessaires pour lancer MPD en tant que service utilisateur au dĂ©marrage dans tous les cas et que ça apporte une rĂ©elle complexitĂ©, on fait le choix de garder MPD en tant que service systĂšme.
Modifiez /etc/samba/smb.conf
. Dans les deux blocs de partages quâon a ajoutĂ© prĂ©cĂ©demment, changez la ligne force user = mpd
en:
force user = user
Puis on peut redémarrer Samba :
sudo systemctl start samba
Permettre à PipeWire de configurer sa priorité
Si vous voyez cela dans les logs de PipeWire :
user@tablette:~$ journalctl --user -fu pipewire
avril 29 13:41:01 tablette systemd[514]: Started pipewire.service - PipeWire Multimedia Service.
avril 29 13:41:01 tablette pipewire[531]: mod.rt: Can't find org.freedesktop.portal.Desktop. Is xdg-desktop-portal running?
avril 29 13:41:01 tablette pipewire[531]: mod.rt: found session bus but no portal
avril 29 13:41:02 tablette pipewire[531]: mod.rt: RTKit error: org.freedesktop.DBus.Error.AccessDenied
avril 29 13:41:02 tablette pipewire[531]: mod.rt: could not set nice-level to -11: Permission non accordée
avril 29 13:41:02 tablette pipewire[531]: mod.rt: RTKit error: org.freedesktop.DBus.Error.AccessDenied
avril 29 13:41:02 tablette pipewire[531]: mod.rt: could not make thread 547 realtime using RTKit: Permission non accordée
Ăa veut grosso modo dire que PipeWire cherche Ă se rendre plus prioritaire via un mĂ©canisme fourni par les environnements de bureau (xdg-desktop-portal), nây arrive pas parce quâĂ©videmment, aucun environnement de bureau ne tourne, alors il essaie de demander au service systĂšme rtkit, et se fait jeter.
Ce nâest pas trĂšs grave et on pourrait vivre sans, mais ça pourrait aider Ă limiter les saccades sonores, donc on va rĂ©parer ça (et je pense avoir vu une bonne amĂ©lioration grĂące à ça).
Le fichier /usr/share/polkit-1/actions/org.freedesktop.RealtimeKit1.policy
dicte qui a le droit ou non de configurer sa prioritĂ© (dĂ©couvert ici, mais le conseil de modifier ce fichier systĂšme nâest pas bon, au moins parce quâune mise Ă jour future risque dâĂ©craser les modifications) :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<policyconfig>
<vendor>Lennart Poettering</vendor>
<action id="org.freedesktop.RealtimeKit1.acquire-high-priority">
<description>Grant high priority scheduling to a user process</description>
<description xml:lang="tr">Bir sĂŒrece yĂŒksek öncelikli çalıĆabilme yetkisi ver</description>
<message>Authentication is required to grant an application high priority scheduling</message>
<message xml:lang="tr">SĂŒrecin yĂŒksek öncelikli çalıĆtırılabilmesi için yetki gerekiyor</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.RealtimeKit1.acquire-real-time">
<description>Grant realtime scheduling to a user process</description>
<description xml:lang="tr">Bir sĂŒrece gerçek zamanlı çalıĆabilme yetkisi ver</description>
<message>Authentication is required to grant an application realtime scheduling</message>
<message xml:lang="tr">SĂŒrecin gerçek zamanlı çalıĆtırılabilmesi için yetki gerekiyor</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
</policyconfig>
Dans un systĂšme Unix, les paramĂštres systĂšmes sont dans /etc
. Pour Polkit, il existe un mĂ©canisme pour Ă©crire des rĂšgles, quâon va utiliser. On va crĂ©er une rĂšgle qui permet Ă nâimporte quel utilisateur du groupe audio
de modifier la prioritĂ© de ses processus. Câest probablement trop large, mais je ne connais pas bien Polkit et ça fera le taf pour notre application dĂ©diĂ©e Ă lâaudio. Si vous avez des meilleures idĂ©es, nâhĂ©sitez pas Ă partager en commentaire.
sudo cat > /etc/polkit-1/rules.d/rt.rules << EOF
polkit.addRule(function(action, subject) {
if (subject.isInGroup("audio") && (
action.id == "org.freedesktop.RealtimeKit1.acquire-high-priority" ||
action.id == "org.freedesktop.RealtimeKit1.acquire-real-time"
)) {
return polkit.Result.YES;
}
})
EOF
sudo systemctl restart polkit.service
systemctl --user restart pipewire
On pourra constater lâabsence des Ă©checs dans les journaux de PipeWire.
Bon, on sent bien que toute cette utilisation audio sans session utilisateur standard nâest pas un cas dâutilisation hyper bien prĂ©vu et on se retrouve Ă toucher des coins un peu sombres du systĂšmeâŠ
Ăvitez les flux Wifi 2,4 GHz
Si vous avez un Wifi en 2,4 GHz, ça peut causer des soucis avec le Bluetooth, et le son peut saccader. Si vous observez cela, il faudra alors limiter au maximum les services et autres tĂąches de fond qui font des communications rĂ©seau. Ăvidemment, si vous pouvez utiliser un cĂąble Ethernet, câest encore mieux.
Sur ce plan, tous les codecs audio Bluetooth ne semblent pas se valoir. Pour tester ça, jâai lancĂ© un test iperf3 entre la tablette et mon ordinateur portable pour saturer le Wifi. Ăa devenait immĂ©diatement catastrophique avec le codec SBC-XQ, alors quâavec le codec Opus 05, il y a initialement des saccades, puis ça sâamĂ©liore vite. Jâimagine que le codec Opus dĂ©grade trĂšs efficacement la qualitĂ© pour compenser. Bon, malheureusement, tous les systĂšmes ne permettent pas de choisir son codec donc ce nâest quâune solution partielle au problĂšme.
Note sur lâutilisation des ressources
C'est léger :
load average: 0,12, 0,10, 0,05
$ free -mh
total utilisé libre partagé tamp/cache disponible
Mem: 986Mi 253Mi 324Mi 6,1Mi 550Mi 733Mi
Ăchange: 974Mi 0B 974Mi
Globalement, le CPU sâennuie en pleine lecture, et Ă peine un tiers du Giga de mĂ©moire vive est utilisĂ©, la partition dâĂ©change sâennuie, donc il y a encore largement la place de faire tourner dâautres trucs sur cet appareil si jamais. On peut aussi constater quâajouter MPD et tout ce bazar Ă une installation existante ne la surchargerait pas plus que ça.
On a aussi un temps de démarrage autour des 20 secondes, ce qui est franchement pas mal.
Conclusion et améliorations possibles
On est pas mal rentrĂ©s dans les dĂ©tails, câĂ©tait lâoccasion dâexplorer plein de choses mine de rien. Jâai Ă la fois appris des choses, prĂ©cisĂ© des connaissances, et mis plein de choses que je savais ensemble pour obtenir un rĂ©sultat trĂšs satisfaisant. On se retrouve Ă manipuler de la gestion de services, des configurations systemd un peu poussĂ©es, du bluetooth, du son avec ALSA et PipeWire, de la gestion de session utilisateur sur un systĂšme headless, et plein dâautres trucs et aller dans les dĂ©tails comme le boot pour avoir quelque chose de rapide, comme lâĂ©cran Ă©teint au bon moment, ou la personnalisation du comportement du bouton power (honnĂȘtement, je nâĂ©tais pas trĂšs sĂ»r que câĂ©tait possible, jâavais lancĂ© la recherche au cas oĂč !).
JâespĂšre que lâaventure vous a plu aussi.
Bien sĂ»r lâensemble est perfectible, alors je vous laisse avec des idĂ©es, nâhĂ©sitez pas Ă partager les vĂŽtres en commentaires :
- Jouer un son au dĂ©marrage / Ă lâappairage Bluetooth. â pour lâinstant, la tablette sâallume et puis plus rien. En gĂ©nĂ©ral, les enceintes Bluetooth jouent un petit son quand elles sont prĂȘtes ou quâelles viennent dâĂȘtre appairĂ©es et ça peut ĂȘtre pratique
- Commande vocale. Il y a clairement des maniĂšres dâutiliser le micro de la tablette pour demander le morceau suivant, prĂ©cĂ©dent ou rĂ©gler le volume. Ăa peut ĂȘtre pratique quand on nâa pas le tĂ©lĂ©phone sous la main et ça peut avoir son petit effet en soirĂ©e la premiĂšre fois, tant que les gens ne sont pas encore complĂštement blasĂ©s par le concept parce que tout le monde nâa pas un Google Nest ou un Alexa chez soi, surtout dans ma bulle sociale. Mais câest probablement finalement trĂšs gadget et je me vois mal interrompre une conversation en criant un ordre pour gĂ©rer la musiqueâŠ
- Appairage Bluetooth plus sĂ©curisĂ©. En gĂ©nĂ©ral, les enceintes Bluetooth acceptent les nouveaux appareils dans un mode spĂ©cial. En appuyant sur le bouton Bluetooth, ou quelque chose comme ça. Ăa peut Ă©viter que les voisin·e·s ne te rickrollent au moment le plus inopportun. Ăa vaudrait le coup de travailler sur quelque chose comme ça. Avec lâĂ©cran tactile, il est probablement possible de dessiner une forme particuliĂšre reconnue (ça serait un peu badasse, ou plus probablement, nâaccepter (une seule) nouvelle connexion que dans les X minutes aprĂšs le dĂ©marrage ou le retour de veille. Comme ça, demander lâappairage consiste Ă appuyer deux fois sur le bouton power, ce qui est plutĂŽt acceptable. Si vous avez des idĂ©es, nâhĂ©sitez pas Ă partagerâŠ
- RĂ©veil Ă distance avec du Wake-on-LAN. Ăa ne sâapplique probablement pas Ă mon matĂ©riel, mais il est possible dâutiliser astucieusement le WoL pour rĂ©veiller l'appareil Ă distance, avec Ă©ventuellement la complicitĂ© dâun routeur ou dâun serveur toujours allumĂ© chez vous.
- DĂ©sactiver le Wifi quand le Bluetooth est utilisĂ©. Pour Ă©viter les interfĂ©rences, on pourrait imaginer que quand un appareil se connecte en Bluetooth, on Ă©teint le Wifi (avec rfkill par exemple), on met MPD en pause (ou on le stoppe sâil est en train de jouer un flux) parce quâon ne peut plus le contrĂŽler, puisque le Wifi nâest plus actif, et on rĂ©active le Wifi quand lâappareil Bluetooth est dĂ©connectĂ©. On pourrait mĂȘme ĂȘtre plus fin et dĂ©tecter quand du son est jouĂ©.
- Automatiquement mettre MPD en pause lors dâune connexion Bluetooth. (un peu doublon avec le prĂ©cĂ©dent point) Pour lâinstant, il faut manuellement mettre en pause mpd, sinon les deux flux audios se jouent en mĂȘme temps. -- Changer la classe Bluetooth de lâappareil. Ăa permettrait Ă lâappareil de se dĂ©clarer comme appareil audio, pour que ça affiche le bon icĂŽne sur les autres appareils.
- Mises à jour automatiques. Il ne faut pas que ça casse des choses en pleine lecture, ni que ça cause des interférences avec le Bluetooth à cause des téléchargements.
-
Ne pas persister les logs. Pour lâinstant, les logs sont Ă©crits dans
/var/log
sur le SSD, entrainant une usure et un ralentissement cependant probablement tous deux nĂ©gligeables. On pourrait vouloir ne pas les garder, mais câest aussi risquer de perdre des informations de dĂ©bogage le jour oĂč il y a un pĂ©pin.
Je vais probablement trouver dâautres choses Ă amĂ©liorer aprĂšs publication de lâarticle. Je partagerai peut-ĂȘtre les choses intĂ©ressantes en commentaires ou dans des journaux, et je ferai peut-ĂȘtre vivre lâarticle sur mon site.
Commentaires : voir le flux Atom ouvrir dans le navigateur