Sistema Hi-Fi digitale a basso costo, con software (quasi) totalmente libero


Raspberry con adattatore WiFi

Raspberry con adattatore WiFi

Lo scopo di questa guida è quello di creare un sistema ad alta fedeltà per ascoltare la nostra musica preferita in modo semplice ed economico.

Perchè parlo di software quasi totalmente libero?
Perchè, come forse qualcuno di voi sa [0], il Raspberry PI necessita di software proprietario per avviarsi oltre ad avere restrizioni sull’utilizzo della GPU (senza dimenticarsi del kernel, linux e non linux-libre). Inoltre, per quanto ne so, non esistono distribuzioni completamente libere per questa scheda.

Tornando al nostro discorso, ci concentreremo sullo use-case RPI connesso via WiFi alla rete domestica, anche se questa guida si può adattare per qualunque sistema GNU/Linux facendo le opportune modifiche (l’unico limite è l’immaginazione 🙂 ).

Ingredienti

  • Un server che abbia un servizio SFTP (SSH File Transfer Protocol) funzionante. Questo può essere un PC, NAS, etc… Qui vengono ospitati i file di musica.
  • il RP (io ho la versione 1 model B – quello con il classico jack audio 3.5 mm)
  • Scheda SD classe 10 (8 GB+)
  • Un computer GNU/Linux per configurare il Raspberry
  • Un adattattore WiFi compatibile (io ho un obsoleto NetGear, Inc. WG111v3 54 Mbps Wireless [realtek RTL8187B])
  • Degli altoparlanti
  • Un cavo audio
  • Smartphone Android oppure un’altro PC che funga da interfaccia di controllo

Cavo audio

Cavo audio

Lato posteriore delle casse

Lato posteriore delle casse

Prerequisiti

  • Tutti i sistemi devono appartenere alla stessa sottorete.
  • Un utente deve avere accesso ai file di musica attraverso SSH, oltre che avere la posibilità di aggiungere chiavi SSH sul server (tipicamente posizionate in ~/.ssh).

Cose che darò per scontato

  • Nome utente Raspberry = audiouser
  • Hostname Raspberry = audio-center
  • Indirizzo IP Raspberry = 192.168.0.23
  • Nome utente server = remote
  • Indirizzo server = 192.168.0.2
  • Directory del server che contiene la musica = /home/remote/MUSIC
  • # = shell root (vedi su)
  • $ = shell di un utente non root

Configurazione

Configurazione di base del RP

Ho scelto Arch Linux [1] come distribuzione da usare in questo progetto per due motivi:

  • È il sistema del quale ho maggior dimestichezza.
  • Non dispone di alcuna interfaccia grafica preinstallata (che risulterebbe inutile per questo progetto).
  • È rolling-release (quindi non ci sono problemi di passaggio di versione).

Su GitHub esiste una guida [2] utile per fare la configurazione di base. Seguiamo i paragrafi con numero:

  • 1 (presente anche sul sito ufficiale [1])
  • 2.1 opzionalmente: se siete connessi via HDMI vi basta fare loadkeys it, in modo da non impazzire con il layout americano della tastiera. Una volta installato il sistema, tutta l’amministrazione sara’ fatta via SSH, quindi non ci sara’ il problema della tastiera. Vedete voi…
  • 2.2
  • 2.3: cambiare Europe/Berlin con Europe/Rome
  • 3.2
  • 3.3
  • 4.1
  • 4.2
  • Sostituiamo il paragrafo 4.3 con i seguenti comandi:
    # useradd -d /home/audiouser -m -G wheel -s /bin/bash audiouser
    # passwd audiouser
    # exit
    $ exit
    
  • Sostituiamo il paragrafo 4.4 con il seguente comando:
    # pacman -S --needed alsa-utils alsa-firmware alsa-lib alsa-plugins
    

    Questo ci consentirà di avere gli strumenti ALSA successivamente.

  • Sostituiamo il paragrafo 7 con i seguenti comandi:

    Ora, colleghiamo il RP all nostra rete via WiFi. Si tratta di disattivare systemd-networkd e di copiare un file di esempio che andremo ad editare.

    # systemctl disable systemd-networkd
    # systemctl disable systemd-networkd
    # cp /etc/netctl/example/wireless-wpa-static /etc/netctl
    # nano /etc/netctl/wireless-wpa-static
    

    Impostiamo i dati della rete secondo le nostre esigenze ([3] per avere maggiori informazioni).

    Abilitiamo il WiFi:

    # systemctl start netctl
    # systemctl enable netctl
    # netctl start wireless-wpa-static
    # netctl enable wireless-wpa-static
    

    e controlliamo con ip addr e con un ping che tutto funzioni a dovere.

    A questo punto possiamo riavviare con # reboot, controllare che si colleghi alla rete e poi fare # poweroff. Ora posizioniamo il Raspberry nella sua destinazione finale, collegandolo alle casse e all’alimentazione.
    D’ora in poi, tutta l’amministrazione sarà fatta da remoto.

    Ci connettiamo al Raspberry e cancelliamo l’utente alarm (in modo da evitare attacchi bruteforce)

    $ ssh audiouser@192.168.0.23
    # userdel alarm
    
  • Infine seguiamo il paragafo 11

Configurazione dell’audio

  • Aggiungiamo l’utente audiouser al gruppo audio, in modo da poter controllare l’audio anche senza essere root ([4] per maggiori informazioni)

    usermod -aG audio audiouser
    
  • Seguiamo quello che ci viene detto al [5] e riavviamo in modo che si possano applicare le modifiche:

    # echo "dtparam=audio=on" >> /boot/config.txt
    # reboot
    
  • A seconda delle fonti è necessario eseguire il seguente comando come root, o come utente normale. Nel dubbio l’ho eseguito in entrambi i modi.
    #/$ amixer cset numid=3 1
    
  • Apriamo $ alsamixer e impostiamo il volume al massimo.
  • Ora testiamo l’audio, come indicato da [6].
    $ speaker-test -c 2
    

    A questo punto dovremmo sentire qualcosa…

Configurazione del mount

  • Generiamo una coppia di chiavi RSA [7] che verrà usata per fare il mount automatico con SSHFS.
    $ ssh-keygen -t rsa -b 4096 -C "$(whoami)@$(hostname)-$(date -I)"
    
  • Copiamo la chiave pubblica sul server. Si può usare il seguente metodo oppure fare un classico copia-incolla (vedere [7] per maggiori informazioni)
    $ ssh-copy-id remote@192.168.0.2
    
  • Testiamo la connessione. Il login dovrebbe essere automatico. Se non è così rivedere i passi precedenti.
    $ ssh remote@192.168.0.2
    $ exit
    
  • Creiamo la cartella di mount della musica
    $ mkdir serverAudio
    
  • Installiamo SSHFS [8]
    # pacman -S sshfs
    
  • Testiamo il mount
    $ sshfs remote@192.168.0.2:MUSIC serverAudio
    
  • Se funziona facciamo la stessa cosa con l’utente root (questo passaggio e’ necessario per la fase successiva – si veda la fonte [8])
    # sshfs remote@192.168.0.2:MUSIC serverAudio
    
  • Controlliamo con $ id le variabili uid e gid e usiamole nel comando successivo

    # echo "remoteuser@192.168.0.2:MUSIC /home/audiouser/serverAudio fuse.sshfs ro,x-systemd.automount,_netdev,user,idmap=user,transform_symlinks,identityfile=/home/audiouser/.ssh/id_rsa,allow_other,default_permissions,uid=1001,gid=1001,umask=0,reconnect,ServerAliveInterval=16,ServerAliveCountMax=1   0 0" >> /etc/fstab
    

    In questo modo verrà fatto il mount automatico della cartella remota MUSIC in ~/serverAudio. Da notare il flag ro per fare in modo che la directory sia di sola lettura. Comunque, giocando con i flag disponibili è possibile migliorare la qualità e la stabilità della connessione.

Configurazione MPD

Configurazione di base

  • Installiamo MPD [9]
    # pacman -S mpd
    
  • Questo è il mio /etc/mpd.conf senza i commenti. Potete importarlo così com’è
    music_directory         "~/serverAudio"
    db_file                 "~/.mpd/database"
    log_file                "~/.mpd/log"
    pid_file                "~/.mpd/pid"
    state_file              "~/.mpd/state"
    sticker_file            "~/.mpd/sticker.sql"
    user                    "audiouser"
    group                   "audiouser"
    bind_to_address         "any"
    port                    "6600"
    log_level               "default"
    metadata_to_use "artist,album,title,track,name,genre,date,composer,performer,disc"
    auto_update             "yes"
    follow_outside_symlinks "yes"
    follow_inside_symlinks  "yes"
    input {
            plugin "curl"
    }
    audio_output {
            type            "alsa"
            name            "default"
            device          "hw:0,0"
            mixer_type      "hardware"
            mixer_device    "default"
            mixer_control   "PCM"
            mixer_index     "0"
            auto_resample   "no"
            auto_format     "no"
            auto_channels   "no"
    }
    

    I valori della sezione audio_output sono tratti da [10] e [11], e dovrebbero garantire la migiore qualità audio possibile.

Riproduzione playlist

  • EXTRA: Aggiungendo le seguenti righe [12], sempre in /etc/mpd.conf è possibile aggiungere la maggior parte delle web radio sotto forma di playlist (per intenderci, attraverso i classici file pls, m3u e extm3u).

    playlist_plugin {
        name "m3u"
        enabled "true"
    }
    
    playlist_plugin {
        name "extm3u"
        enabled "true"
    }
    
    playlist_plugin {
        name "pls"
        enabled "true"
    }
    

    L’unica cosa da fare è creare una cartella streams (nome di esempio) nel server remoto, dove andremo a mettere tutti questi file:

    $ ssh remote@192.168.0.2
    $ cd MUSIC
    $ mkdir streams
    $ cd streams
    $ wget <URL dei file pls, m3u o extm3u>
    $ exit
    

    Successivamente, le interfacce di controllo tratteranno questi file esattamente come normali file di musica.

Riproduzione CD

  • EXTRA: Volendo vedere fino a che punto si possa spingere questo progetto, ho deciso di aggiungere anche il supporto
    per CD. Avendo un masterizzatore USB (quindi esterno), comprato qualche anno fa, che utilizzo molto raramente, mi sono detto perchè no 🙂

    E qui le cose si fanno interessanti… Per completezza propongo due soluzioni. La prima è quasi banale ma non funziona in modo decente.
    La seconda comprende caratteristiche molto utili, tuttavia non è integrata con MPD. Viene infatti usato mplayer per riprodurre i CD.

    In entrambi i casi è necessario installare mpc, cioè l’interfaccia di controllo per mpd,
    oltre che aggiungere il nostro utente al gruppo optical [4]:

    # pacman -S mpc
    # gpasswd -a audiouser optical
    # reboot
    
  • Soluzione semplice
    • Applichiamo il punto precedente della guida (Riproduzione playlist
    • Aggiungiamo le seguenti righe in /etc/mpd.conf, come descritto nella documentazione ufficiale di MPD [13]:
      input {
              plugin "cdio_paranoia"
      }
      

      Questo semplicemente abilita la possibità di riprodurre i CD.

    • Ora, riavviamo mpd e testiamo la cosa:
      # systemctl restart mpd
      $ mpc add cdda://
      $ mpc play
      

      Se tutto funziona fermiamo la lettura:

      $ mpc clear
      
    • Entriamo nel server:
      $ ssh remote@192.168.0.2
      $ cd MUSIC
      $ cd streams
      

      e creiamo una playlist come la seguente da salvare in un file chiamato cd.pls:

      
      numberofentries=1
      File1=cdda://
      Title1=Local CD player
      Length1=-1
      version=2
      
    • Infine facciamo il logout
      $ exit
      
    • Probabilmente avrete notato che la riproduzione è “choppy”, cioè funziona per qualche secondo, poi va in pausa per il buffering e così via – molto fastidioso e inaccettabile. Per ascoltare un CD è inoltre necessario aprire l’interfaccia. Ho pensato che sarebbe stato più bello fare una cosa del genere (nota lo pseudocodice di altissimo livello):

      < l'utente inserisce il CD >
      < il computer rileva una cambiamento nello stato del lettore CD  >
      < se c'è già una playlist in esecuzione su MPD >
      < allora la playlist viene messa in pausa >
      < flag playlist_active = true >
      < viene avviata la riproduzione del CD >
      < una volta finito, viene espulso il CD >
      < se playlist_active allora viene ripresa la playlist precedentemente in esecuzione >
      

      Leggete il punto successivo per capire come fare (quasi) tutto questo.

    Soluzione smart
      Per esaudire tutti i requisiti precedenti, in particolare l’istruzione il computer rileva una cambiamento nello stato del lettore CD
      possiamo usare un sistema già integrato chiamato udev. Questo è in grado di “ascoltare” gli eventi kernel legati alle periferiche. Per esempio se inserisco una chiavetta USB, posso vedere l’evento con il comando $ dmesg. Qui vengono date molte informazioni fra cui dimensioni delle partizioni, misteriosi id, il nome che il sistema da alla periferica (/dev/qualcosa), etc… Ora, mettendo insieme varie fonti [14] [15] [16] [17] sono riuscito a scrivere una semplice regola per l’istruzione voluta.

    • Creiamo il file /etc/udev/rules.d/10-optical.rules con i seguenti contenuti:
      ACTION=="change", SUBSYSTEM=="block", KERNEL=="sr0", DRIVER=="", SYMLINK+="cdrom", RUN+="/usr/bin/systemctl --no-block restart cd-autoplay.service"
      

      Questo significa: quando c’è un cambiamento in /dev/sr0 avvia il programma definito nella variabile RUN. Nel nostro caso il programma è un servizio systemd che andremo a scrivere in un attimo. /dev/sr0 è il tipico nome kernel dato al lettore CD. Per quanto ho capito le azioni sono tipicamente add, change e remove. Dopo aver controllato con # udevadm monitor e come descritto nella fonte [15] l’unica azione che si verifica quando si inserisce (o si espelle) un CD è change. Le altre due si verificano quando attacco (add) e stacco (remove) l’USB del lettore.

    • Ora creiamo un servizio systemd molto semplice in /etc/systemd/system/cd-autoplay.service:
      [Unit]
      Description="Autoplay Audio CD"
      
      [Service]
      Type=simple
      ExecStart=/home/audiouser/cdAutoplay.sh
      

      Come si può facilmente intuire, se avviato, chiamerà ~/cdAutoplay.sh

    • E adesso lo script vero e proprio in /home/audiouser/cdAutoplay.sh
      #!/usr/bin/bash
      
      cacheSize="1024"
      
      # Very raw. It would be better if playlist was saved then
      # restored at the end.
      mpc clear
      mplayer cdda://:1 -cache "$cacheSize"
      eject
      

      Nota bene che lo script è davvero base e non fa tutto quello che ho promesso prima. Semplicemente cancella la playlist di MPD, legge il disco e alla fine lo espelle.
      Non ho ancora avuto tempo per affinarlo, comunque sono sicuro che si possa fare senza troppe difficoltà. L’istruzione eject espelle il CD da /dev/cdrom (che è un link simbolico a /dev/sr0; quindi la cosa torna…). Per quanto riguarda mplayer, nella wiki di Arch [18] è spiegato come risolvere il problema dell’audio “choppy” citato prima e che cosa fa veramente quel comando.

      Infine è da notare che lo script viene eseguito come utente root, quindi attenzione.

    • Adesso, installiamo mplayer, riavviamo e proviamo tutto inserendo un CD.
      # pacman -S mplayer
      # reboot
      

Finalizzazione configurazione MPD

  • Ora modifichiamo il servizio di Systemd. Sarebbe più corretto fare un override perchè ho notato che dopo un aggiornamento si era sovrascritta l’impostazione. Comunque,
    # nano /usr/lib/systemd/system/mpd.service
    

    Dentro alla sezione [Service] modificare la variable user mettendoci il nostro nome utente

    user=audiouser
    
  • Facciamo ripartire il servizio
    # systemctl daemon-reload
    # systemctl restart mpd
    
  • Controlliamo lo stato di MPD. Personalmente ho avuto problemi con dei permessi. Per risolverli ho semplicemente creato i file ($ touch) e le cartelle ($ mkdir) che il sistema mi indicava come problematici.
    $ systemctl status mpd
    

NOTA: l’idea di usare MPD mi è venuta leggendo [19]. Tuttavia viene proposto di usare DLNA. Quando l’ho provato, ho notato che non era possibile riprodurre i file. Inoltre non erano disponibili tutte le funzionalità. Usare SSHFS invece è un “trucco” per fare credere a MPD che i file fanno parte dell’albero delle directory.

Android oppure GNU/Linux

A questo punto possiamo installare l’interfaccia di controllo su Android chiamata MPDroid [20]. Per GNU/Linux esiste più di un programma. Io ho provato Sonata [21]. Inseriamo indirizzo (192.168.0.23) e porta (6600), e finalmente possiamo ascoltare la musica (possibilmente in formato FLAC 🙂 )

Andare oltre questo post

Un passaggio che non ho ancora fatto è quello di aggiungere la possibilità di usare commandi di amministrazione attraverso Android. Al posto di usare il classico ConnectBot [22] ho pensato che sarebbe più interessante Mercury-SSH [23]. Questa app permette di creare comandi preimpostati attraverso file JSON. Banalmente mi viene in mente di creare comandi per lo spegnimento, il riavvio, etc…

A presto…

Fonti

[0] https://www.fsf.org/resources/hw/single-board-computers
[1] https://archlinuxarm.org/platforms/armv6/raspberry-pi
[2] https://github.com/phortx/Raspberry-Pi-Setup-Guide#
[3] https://wiki.archlinux.org/index.php/Netctl
[4] https://wiki.archlinux.org/index.php/Users_and_groups#Pre-systemd_groups
[5] https://wiki.archlinux.org/index.php/Raspberry_Pi
[6] https://wiki.archlinux.org/index.php/Advanced_Linux_Sound_Architecture
[7] https://wiki.archlinux.org/index.php/SSH_keys
[8] https://wiki.archlinux.org/index.php/SSHFS
[9] https://wiki.archlinux.org/index.php/Music_Player_Daemon
[10] https://lacocina.nl/audiophile-mpd
[11] https://github.com/ronalde/mpd-configure#background
[12] https://www.musicpd.org/doc/user/playlist_plugins.html
[13] https://www.musicpd.org/doc/user/input_plugins.html#idm771
[14] http://askubuntu.com/questions/359855/how-to-detect-insertion-of-dvd-disc
[15] https://wiki.archlinux.org/index.php/Udev
[16] http://www.reactivated.net/writing_udev_rules.html
[17] https://forums.opensuse.org/showthread.php/485261-Script-run-from-udev-rule-gets-killed-shortly-after-start
[18] https://wiki.archlinux.org/index.php/MPlayer#Choppy_audio_CD_playback
[19] http://www.lesbonscomptes.com/pages/mpd-upnp.html
[20] https://f-droid.org/repository/browse/?fdfilter=mpd&fdid=com.namelessdev.mpdroid
[21] https://sourceforge.net/projects/sonata.berlios/
[22] https://f-droid.org/repository/browse/?fdfilter=connectbot&fdid=org.connectbot
[23] https://f-droid.org/repository/browse/?fdfilter=mercur&fdid=it.skarafaz.mercury

Annunci

2 pensieri su “Sistema Hi-Fi digitale a basso costo, con software (quasi) totalmente libero

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...