Raspberry Pi: Internet Ràdio
Contingut
Introducció
El que es busca és una cosa molt mínima, amb un sol pulsador. Apretar dues vegades ràpidament el botó per engegar/aturar la ràdio. Si està engegada, en anar apretant vaig canviant d'emissora.
Desenvolupament
Em baso en:
i concretament en Setting up MPD and MPC:
Tot el sistema està basat en mpd (music player daemon) i mpc (music player client), que són el servidor i el client (el client controla el servidor)
$ sudo apt-get install mpd mpc
El fitxer de configuració és /etc/mpd.conf
De la directiva audio_output no toco res:
audio_output { type "alsa" name "My ALSA Device" device "hw:0,0" # optional format "44100:16:2" # optional mixer_device "default" # optional mixer_control "PCM" # optional mixer_index "0" # optional }
i de la directiva audio_input el link diu de registrar-se a last.fm (http://www.last.fm/) (jo ho he fet, joanillo/jq****), però en realitat he comprovat que no cal. La única cosa que necessita audio_input és una línia que posi plugin, encara que estigui buida:
input { # plugin "lastfm" # user "joanillo" # password "jq****" plugin "" # plugin "curl" # proxy "proxy.isp.com:8080" # proxy_user "user" # proxy_password "password" }
per tant la cosa queda molt simple.
last.fm és interessant perquè tenen una API i per tant pots programar les teves pròpies aplicacions d'escriptori o per a mòbil. Però d'altra banda sembla ser que tenen bastants problemes de llicències.
A /etc/modules he de fer referència al xip que té la RP, que és el SoC de Broadcom 2835:
snd_bcm2835
Tenim dos sortides d'audio: el jack stereo (sortida 1), i HDMI (sortida 2):
$ sudo amixer cset numid=3 1
Ara ja podem reiniciar el servei mpd:
$ sudo /etc/init.d/mpd restart
i puc començar a escoltar música:
$ mpc volume:100% repeat: on random: off single: off consume: off $ mpc add http://s1.radio.lclhst.net:1337/ $ mpc play Minimal, Techno, Electro Sets @ http://radio.lclhst.net/: Patrick Schulz - Promotional Mix - October 2008 [playing] #1/1 0:04/0:00 (0%) volume:100% repeat: on random: off single: off consume: off
funciona perfectament. A mi no em surt volume:100%, sinó que em surt volume: n/c.
Per controlar el volum per línia de comanda seria:
$ mpc volume 100
però a mi no em funciona (tot i que per defecte s'escolta bé al 100%). Si vull que funcioni he de fer:
$ joe /etc/mpd/mpd.conf i descomentar mixer_type "software"
aleshores ja puc controlar el volum per línia de comanda
$ mpc volume 50 $ mpc volume 100
Llistes de ràdio
He provat amb una ràdio d'Internet que fa música electrònica:
Server Status: Server is currently up and public. Stream Title: Minimal, Techno, Electro Sets @ http://radio.lclhst.net/ Stream Genre: Electronic Current Song: Wighnomy Brothers - Klangkino 30.10.2008
Si vull afegir noves ràdios ho faig amb la comanda add:
mpc add http://s1.radio.lclhst.net:1337/ mpc add http://s3.radio.lclhst.net:1337/
i veig les ràdios actives amb
$ mpc playlist
Puc fer sonar la primera o la segona ràdio fent:
$ mpc play 1 $ mpc play 2
Per esborrar la llista de ràdios:
$ mpc clear
Com trobo d'altres ràdios disponibles?:
És fàcil utilitzar les que tenen el format que conec. Per exemple:
# ACE FM $ mpc add http://208.43.9.96:8106/ # vaughan radio mpc add http://vaughanradio.streaming-pro.com:8012/ # disco music radio mpc add http://www.discomusicradio.com:8100/
També hi ha una classificació per gèneres. Per escoltar jazz:
per ex,
Ara bé, què passa amb les URL que tenen format pls o m3u. Doncs molt fàcil, són fitxers de text que a dins tenen la URL a utilitzar. Una URL o vàries, doncs poden ser playlists.
Per exemple, amb iCatJazz, el contingut del fitxer http://directe-http.emissio.catradio.cat:8000/catradio.cat/icat_jazz.m3u és http://directe-http.emissio.catradio.cat:8000/catradio.cat/icat_jazz, i només s'ha de fer:
$ mpc add http://directe-http.emissio.catradio.cat:8000/catradio.cat/icat_jazz
El mateix per als fitxers pls:
$ cat aac_jazz.pls [playlist] File1=http://188.165.20.29:8750 Title1=Server1-> >>> P O L S K A S T A C J A <<< - JAZZ (AACPLUS - Wymagany nowy winamp!) Length1=-1 File2=http://188.165.22.29:8750 Title2=Server2-> >>> P O L S K A S T A C J A <<< - JAZZ (AACPLUS - Wymagany nowy winamp!) Length2=-1 File3=http://87.98.236.207:80 Title3=Server3-> >>> P O L S K A S T A C J A <<< - JAZZ (AACPLUS - Wymagany nowy winamp!) Length3=-1 File4=http://91.121.92.167:8700 Title4=Server1-> >>> P O L S K A S T A C J A <<<- JAZZ Length4=-1 NumberOfEntries=4 Version=2
En aquest cas veig que conté diversos fitxers.
$ mpc playlist ICat Jazz >>> POLSKASTACJA .PL >>> - JAZZ (Polskie Radio),aacplus: Gerry Mulligan - Blues For Gerry
Es pot obtenir directament la informació que hi ha dins els fitxers (http://www.raspberrypi.org/phpBB3/viewtopic.php?f=9&t=4031). Un exemple de codi amb bash per obtenir Los 40 principales seria:
#!/bin/bash rm LOS40* wget http://provisioning.streamtheworld.com/pls/LOS40.pls grep "File1=" LOS40.pls > streamaddr mpc clear mpc add $(sed 's/File1=//g' streamaddr) mpc play
es tracta d'extreure la informació que hi ha dins el fitxer.
D'altres ràdios:
- iCatFM: http://directe-http.emissio.catradio.cat:8000/catradio.cat/tot_cat
- Catalunya Ràdio: http://directe-http.emissio.catradio.cat:8000/catradio.cat/cat_radio
Recuperar la informació d'allò que estic escoltant
$ mpc playlist ICat Jazz >>> POLSKASTACJA .PL >>> - JAZZ (Polskie Radio),aacplus: Gerry Mulligan - Blues For Gerry $ mpc play 1 $ mpc play 2
Amb l'opció -f puc filtrar la informació que em dona la comanda playlist:
$ mpc -f "[[%artist% - ]%title%]|[%file%]" playlist http://directe-http.emissio.catradio.cat:8000/catradio.cat/icat_jazz Fourplay - Put Our Hearts Together (Vocal Version) $ mpc -f "[%title%]" playlist Fourplay - Put Our Hearts Together (Vocal Version)
Programació
Es tracta de programar els scripts per arrencar/aturar el servidor mpd, i llegir les llstes de ràdio que he seleccionat. L'electrònica necessària és mínima, tant sols cal un botó i programar un pin GPIO. Evidentment la cosa es pot complicar amb una pantalla LCD per saber què estic escoltant, més botons, etc,... però no és l'objectiu.
El primer que hem de fer és que el dimoni mpd no arrenqui en l'inici del sistema. Un podria pensar que seria tan fàcil com canviar true per false en el fitxer /etc/init.d/mpd, però no. La solució està més avall, desactivar el dimoni amb rc-update.
radio_internet_v1.sh (versió 1):
#!/bin/bash #functions start_mpd () { echo Starting mpd... /etc/init.d/mpd start sleep 2 } stop_mpd () { echo Stopping mpd... /etc/init.d/mpd stop sleep 2 } play_radio () { echo ${MYARRAY[$id_radio]} mpc clear mpc add ${MYARRAY[$id_radio]} mpc play } #main program llista="radio_internet.txt" index=0 while read line ; do MYARRAY[$index]="$line" index=$(($index+1)) done < $llista echo ${MYARRAY[0]}: ${MYARRAY[1]} echo $index RANG=$((($index+1)/2)) number=$RANDOM let "number %= $RANG" # ^^ #echo "Random number less than $RANG --- $number" id_radio=$((($number*2)+1)) echo "radio seleccionada: $id_radio" #start_mpd play_radio
i la versió 4, radio_internet_v4.sh queda:
#!/bin/bash #led red=0 #botó button=8 # functions: setup () { gpio mode $red out gpio mode $button in } waitButton1sttime () { while [ `gpio read $button` = 1 ]; do espera=1 sleep 0.03 done #from: http://stackoverflow.com/questions/3683434/using-time-command-in-bash-script # UNIX timestamp concatenated with nanoseconds T="$(date +%s%N)" while [ `gpio read $button` = 0 ]; do sleep 0.03 done } waitButton2ndtime () { T1="$(($(date +%s%N)-T))" while [ `gpio read $button` = 1 ] && [ $T1 -le 300000000 ]; do sleep 0.03 # Time interval in nanoseconds T1="$(($(date +%s%N)-T))" done while [ `gpio read $button` = 0 ]; do sleep 0.03 done if [ $T1 -le 300000000 ]; then #echo "start/stop dimoni" start_stop_mpd else #echo "canvi de canal" canvi_canal fi } start_stop_mpd () { for i in {1..5} do gpio write $red 1 sleep .02 gpio write $red 0 sleep .02 done if [ -z `pidof -s mpd` ]; then echo "Starting mpd..." /etc/init.d/mpd start else echo "Stopping mpd..." /etc/init.d/mpd stop fi for i in {1..5} do gpio write $red 1 sleep .02 gpio write $red 0 sleep .02 done } canvi_canal () { if [ $id_radio -le $(($index-3)) ]; then id_radio=$(($id_radio+2)) else id_radio=1 fi echo echo ${MYARRAY[($id_radio-1)]} gpio write $red 1 mpc clear mpc add ${MYARRAY[$id_radio]} mpc play gpio write $red 0 } #main program llista="radio_internet.txt" index=0 while read line ; do MYARRAY[$index]="$line" index=$(($index+1)) done < $llista #RANG=$((($index+1)/2)) #number=$RANDOM #let "number %= $RANG" ##echo "Random number less than $RANG --- $number" #id_radio=$((($number*2)+1)) echo Raspberry Pi Internet Radio echo Joan Quintana - joanillo echo www.joanillo.org echo Dec 2012 echo setup while true; do waitButton1sttime waitButton2ndtime done
el ftixer on tinc les emissores és, per exemple (és una barreja d'emissores sense cap criteri). (No oblidar-se un retorn de carro al final). Fitxer radio_internet.txt:
#1 Catalunya Ràdio http://directe-http.emissio.catradio.cat:8000/catradio.cat/cat_radio #2 iCatFM http://directe-http.emissio.catradio.cat:8000/catradio.cat/tot_cat #3 iCat JAZZ http://directe-http.emissio.catradio.cat:8000/catradio.cat/icat_jazz #4 JAZZ AACPlus http://188.165.20.29:8750 #5 Los 40 Principales http://5253.live.streamtheworld.com:80/LOS40_SC #6 Minimal, Techno, Electro Sets http://s1.radio.lclhst.net:1337/ #7 ACE FM http://208.43.9.96:8106/ #8 vaughan radio http://vaughanradio.streaming-pro.com:8012/ #9 Catalunya Música http://directe-http.emissio.catradio.cat:8000/catradio.cat/cat_classica
Ara només falta que aquest script s'executi en l'inici del sistema...
script inici del sistema
Es tracta de què s'executi el script com a root, una sola vegada, i abans d'iniciar sessió. Es tracta de ficar el script en el directori /etc/init.d, com si fos un dimoni. Demonitzar un script és en teoria fàcil, a la pràctica no ho és tant. La solució que a mi m'ha funcionat, pas per pas, és:
1. Primer de tot eliminar el dimoni mpd de l'inici automàtic del sistema. Això es fa fent update-rc mpd remove, o bé eliminar els softlinks que fan referència a mpd en els directoris /etc/rc.0 a /etc/rc.6.
2. copio radio_internet_vx.sh i radio_internet.txt al directori /etc/init.d
3. és important en el script ficar les rutes absolutes. Per exemple, substituir gpio per /usr/local/bin/gpio; sleep per /bin/sleep; date per /bin/date; mpc /usr/bin/mpc. Però això és clar és una tonteria. És millor ficar al principi de tot:
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
i el que sí que és important és ficar la ruta del fitxer on estan les emissores:
llista="/etc/init.d/radio_internet.txt"
4. Aprofitarem el script rc.local (i així m'evitaré fer els softlinks per al meu script). editar el fitxer /etc/init.d/rc.local i afegim una línia:
do_start() { bash /etc/init.d/radio_internet_v4.sh if [ -x /etc/rc.local ]; then ...
El que fa aquest script és comprovar si existeix el directori rc.local (que existeix a Ubuntu però no pas a Debian). Jo el que faig és executar aquest script abans de fer la comprovació de l'existència de la carpeta. I el que és important és no oblidar-se el bash al davant.
5. reiniciem la BP i comprovem que arrenca bé el script
$ shutdown -r now
reconnectem
$ ssh pi@192.168.1.138 $ ps aux | grep mpd $ ps aux | grep radio root 1932 5.8 0.6 2796 1252 ? S 22:17 0:03 bash /etc/init.d/radio_internet_v4.sh
radio_internet_v6.sh: (canvi: he canviat el pin al qual està connectat el botó. El pin 8 passa a ser el pin 1, però aquest canvi no és trivial, doncs per al pin 1 he de programar que estigui habilitat la resistència de pull-up, veure més avall)
#!/bin/bash PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin #led red=0 #botó #button=8 button=1 # functions: setup () { gpio mode $red out #gpio mode $button in gpio mode $button up } waitButton1sttime () { while [ `gpio read $button` = 1 ]; do sleep 0.03 done #from: http://stackoverflow.com/questions/3683434/using-time-command-in-bash-script # UNIX timestamp concatenated with nanoseconds T="$(date +%s%N)" while [ `/usr/local/bin/gpio read $button` = 0 ]; do sleep 0.03 done } waitButton2ndtime () { T1="$(($(date +%s%N)-T))" while [ `gpio read $button` = 1 ] && [ $T1 -le 300000000 ]; do sleep 0.03 # Time interval in nanoseconds T1="$(($(date +%s%N)-T))" done while [ `gpio read $button` = 0 ]; do sleep 0.03 done if [ $T1 -le 300000000 ]; then #echo "start/stop dimoni" start_stop_mpd else #echo "canvi de canal" canvi_canal fi } start_stop_mpd () { for i in {1..5} do gpio write $red 1 sleep .02 gpio write $red 0 sleep .02 done if [ -z `pidof -s mpd` ]; then echo "Starting mpd..." /etc/init.d/mpd start else echo "Stopping mpd..." /etc/init.d/mpd stop fi for i in {1..5} do gpio write $red 1 sleep .02 gpio write $red 0 sleep .02 done } canvi_canal () { if [ $id_radio -le $(($index-3)) ]; then id_radio=$(($id_radio+2)) else id_radio=1 fi echo echo ${MYARRAY[($id_radio-1)]} gpio write $red 1 mpc clear mpc add ${MYARRAY[$id_radio]} mpc play gpio write $red 0 } #main program llista="/etc/init.d/radio_internet.txt" index=0 while read line ; do MYARRAY[$index]="$line" index=$(($index+1)) done < $llista #RANG=$((($index+1)/2)) #number=$RANDOM #let "number %= $RANG" ##echo "Random number less than $RANG --- $number" #id_radio=$((($number*2)+1)) echo Raspberry Pi Internet Radio echo Joan Quintana - joanillo echo www.joanillo.org echo Dec 2012 echo setup while true; do waitButton1sttime waitButton2ndtime done
Llistat d'emissores de Jazz europees
I aquí va el fitxer on tinc llistades 40 emissores de Jazz que funcionen per Internet: (radio_internet_jazz.txt)
# iCat Jazz Barcelona http://directe-http.emissio.catradio.cat:8000/catradio.cat/icat_jazz # Crooze.fm Antwerp Belgium http://193.227.114.74:9000/ # Jazz FM Sofia Bulgaria http://live.btvradio.bg:8000/jazz-fm.mp3 # Ro Jazz Prague http://stream3.rozhlas.cz:8000/jazz_low.ogg # DR P8 Jazz Copenhagen http://live-icy.gss.dr.dk:8000/A/A22H.mp3 # Jazz Radio Lyon http://broadcast.infomaniak.net:80/jazzradio-high.mp3 # Jazz Radio Classic Jazz Lyon http://broadcast.infomaniak.net:80/jazz-wr01-128.mp3 # Jazz Radio Manouche Lyon http://broadcast.infomaniak.net:80/jazz-wr02-128.mp3 # Jazz Radio New Orleans Lyon http://broadcast.infomaniak.net:80/jazz-wr03-128.mp3 # Jazz Radio Electro Swing Lyon http://broadcast.infomaniak.net:80/jazz-wr04-128.mp3 # Jazz Radio Jazz Contemporary Lyon http://broadcast.infomaniak.net:80/jazz-wr05-128.mp3 # Jazz Radio Jazz Funk Lyon http://broadcast.infomaniak.net:80/jazz-wr06-128.mp3 # Jazz Radio Jazz Gospel Lyon http://broadcast.infomaniak.net:80/jazz-wr07-128.mp3 # Jazz Radio Jazz Groove Lyon http://broadcast.infomaniak.net:80/jazz-wr08-128.mp3 # Jazz Radio Jazz Latin Lyon http://broadcast.infomaniak.net:80/jazz-wr09-128.mp3 # Jazz Radio Jazz Soul Lyon http://broadcast.infomaniak.net:80/jazz-wr10-128.mp3 # Jazz Radio Jazz Soul Food Lyon http://broadcast.infomaniak.net:80/jazz-wr12-128.mp3 # Jazz Radio Black Music Lyon http://broadcast.infomaniak.net:80/jazzblackmusic-high.mp3 # Jazz Radio Blues Lyon http://broadcast.infomaniak.net:80/jazzblues-high.mp3 # Jazz Radio Ladies & Crooners Lyon http://broadcast.infomaniak.net:80/jazzladiescrooners-high.mp3 # Jazz Radio Lounge Lyon http://broadcast.infomaniak.net:80/jazzlounge-high.mp3 # LinasJazz http://87.98.175.43:8010 # Swing FM Limoges http://radio.swingfm.asso.fr:8000 # TSF Jazz Paris http://tsfjazz.ice.infomaniak.ch:80/tsfjazz-high # JazzRadio 101.9 Berlin http://84.16.227.59:8250/;stream.mp3 # Coolradio Jazz Ingolstadt Germany http://178.32.115.9:7040/coolradio-jazz-aac48.aacp # FFH Digital Jazz Frankfurt http://mp3.ffh.de/ffhchannels/hqjazz.mp3 # SR 2 - Off-Beat Saarbrücken Germany http://gffstream.ic.llnwd.net/stream/gffstream_w25a # Jazz Radio Budapest http://194.38.105.21:8002/ # 90.9 Jazzy Budapest http://online.jazzy.hu:80/stream/1/ # Jazz FM Skopje Macedonia http://217.16.69.17:8000/jazz.mp3 # Radio 6 Jazz Hilversum Netherlands http://icecast.omroep.nl:80/radio6-jazzjong-mp3 # NRK Jazz Oslo http://lyd.nrk.no:80/nrk_radio_jazz_aac_h # RadioJAZZ.fm Poland http://stream.radiojazz.fm:8000/radiojazzfm-hi.mp3 # PolskaStacja Jazz Poland http://188.165.20.29:8750 # RMF Smooth Jazz Kraków http://files.kusmierz.be/rmf/smoothjazz-1facts.mp3 # Radio Crazy Jazz Switzerland http://stream2138.init7.net:80 # Radio Crazy Modern Jazz Switzerland http://stream2140.init7.net:80 # TSTU Jazz Ternopil Ukraine http://radio.tstu.edu.ua:8000/jazz # Jazz FM London http://listen.onmyradio.net:8002/
pull-up pull-down resistors
Fins ara hem utilitzat la següent configuració, doncs el tutorial que seguia deia que aquest pin tenia un pull-up resistor.
button=8 gpio mode $button input
Bé, en general, els pins tenen tan un pull-up com un pull-down resistor, i es pot programar. Si jo faig button=1 el programa deixa de funcionar (suposo que per defecte està connectat al pull-down). Per tal de què funcioni per capturar senyals d'entrada he de fer servir la resistència de pull-up, i això es fa de la següent manera.
button=1 gpio mode $button up
En qualsevol cas, és un tema que no he trobat una informació clara i precisa. La man page de gpio diu:
mode <pin> <mode> Set a pin into input, output or pwm mode. Can also use the literals up, down or tri to set the internal pull-up, pull-down or tristate (off) controls
Un tutorial de buttons i switches: http://www.cl.cam.ac.uk/~db434/raspi/buttons_and_switches/
Enllaços
creat per Joan Quintana Compte, desembre 2012