BASH программы для wifi радио.
Jan. 31st, 2014 12:06 amУ американца было два скрипта: interface.sh и display2.sh. Interface.sh - это основная программа, которая выполняет запуск display2.sh, обрабатывает данные полученные с arduino и запускает воспроизведение конкретной станции на wifi радио.
В моем варианте, display2.sh превратился в скрипт lcd.sh и добавилось еще три файла.
- station-list.sh с массивам содержащим ссылки на аудиопотоки (vAddr), их имена (vName) и число каналов (STATIONS). Как искать ссылки на радио описал здесь.
- time.sh посылающий раз в секунду сообщение о текущем времени. Текущее время имеет формат "<три буквы дня недели> DD.MM.YY hh:mm".
- SendToTTY.sh посылающий раз в три секунды число доступных станций.
Несколько важных замечаний.
1. Для работы моих скриптов требуется интерпретатор команд bash, ибо busybox не понимает массивы.
2. Сообщения в arduino нельзя слать без паузы, хотя это и напрашивается в скрипте SendToTTY.sh, ибо тогда перегрузиться arduino.
3. В качестве устройства терминала надо использовать "/dev/ttyATH0" (название устройства последовательного порта в версии Attitude Adjustment прошивки openwrt), а не "/dev/tts/0" (последовательный порт в версии Kamikaze прошивки openwrt используемой mightyohm).
4. Некоторые станции работать будут воспроизводиться с заеданиями, это вызвано отсутствием математического сопроцессора в ЦПУ роутера: кодеки с использующие инструкции с плавающей точкой работают в роуторе очень медленно. Чаще всего это будут потоки закодированные "aac" или с измененным расширением с flv на mp3 по моему рецепту. Рекомендации гуляющие по интернету по замене поций компилирования с эмуляции плавающей запятой на фиксированную не помогают.
5. Для воспроизведения без ежесекундных пауз необходимо доработать файл "/etc/mpd.conf": разкоментировать блок описывающий устройство oss.
# An example of an OSS output:
#
audio_output {
type "oss"
name "My OSS Device"
device "/dev/dsp" # optional
format "44100:16:2" # optional
## mixer_type "hardware" # optional
## mixer_device "/dev/mixer" # optional
## mixer_control "PCM" # optional}6. Американец требует что бы его имя сохранили в любом коде производном от его, я это сделал.# This work is protected by the
# Creative Commons Attribution-Share Alike 3.0 United States License.
# http://creativecommons.org/licenses/by-sa/3.0/us/
#
Файл interface.sh.
#!/bin/bash
#**********************************************************************************
#* скрипт interface.sh - это основная bash программа для реализации wifi радио, *
#* сделано по рецепту американца mightyohm *
#* (http://mightyohm.com/blog/2008/10/building-a-wifi-radio-part-1-introduction/) *
#* 09.02.2014 zepete.livejournal.com *
#**********************************************************************************
#include station database
source '/root/station-list.sh'
declare -r -i VOLUME=100
declare -r -i MAXADC=512
declare -i oldstation=0
declare -r -i ADCBIN=($MAXADC-1)/$STATIONS
function GetNumOfStation ()
{
inputline="" # clear input
# Loop until we get a valid tuner position from the AVR
until inputline=$(echo $inputline | grep -e "^Tuner: *[0-9]*$")
do
inputline=$(head -n 1 < /dev/ttyATH0)
if echo $inputline | grep -e "^Arduino waiting TPL" # get requist for reboot
then
reboot
fi
done
value=$(echo $inputline | sed 's/^Tuner: *//') # strip out the tuner: part
# if station has changed, we need to change position in the playlist
if [ "$value" -ne "$oldstation" ]
then
mpc play $[$value + 1]
oldstation=$value
until mpc | grep "\[playing\] \#$[$value + 1]/"
do
mpc play $[$value + 1]
done
echo ${value}. ${vName[$value]} > /dev/ttyATH0
fi
}
trap 'echo can not stop' SIGINT # on ctrl-c, useful for debugging
until ps | grep -v grep | grep -q mpd
do
sleep 1
done
stty 9600 < /dev/ttyATH0 # set serial port to 9600 baud
stty -echo < /dev/ttyATH0 # no echo
# so we can talk to the AVR
# turn off local echo to make TX/RX directions
# completely separate from each other
mpc volume $VOLUME # adjust this to suit your speakers/amplifier
mpc clear # clear current playlist
# build a playlist, substitute your favorite radio stations here
# the first line becomes station #1, and so on.
for ((i=0;i<$STATIONS;i++))
do
echo ${vAddr[$i]}
mpc add ${vAddr[$i]}
done
mpc playlist # show the resulting playlist
# Tell the AVR we're ready to start doing stuff
/root/SendToTTY.sh &
#waiting first tuner: nember
GetNumOfStation
killall SendToTTY.sh
# launch LCD display routines in the background
/root/lcd.sh &
/root/time.sh &
while true # loop forever
do
GetNumOfStation
done
Файл lcd.sh#!/bin/bash
#**********************************************************************************
#* скрипт interface.sh - это bash программа для реализации wifi радио, *
#* посылает в arduino имя проигрываемой радиостанции или имя ошибки при *
#* воспроизведении, сделано по рецепту американца mightyohm *
#* (http://mightyohm.com/blog/2008/10/building-a-wifi-radio-part-1-introduction/) *
#* 09.02.2014 zepete.livejournal.com *
#**********************************************************************************
source '/root/station-list.sh'
trap 'echo "pressed ctrl-c"' SIGINT
OLD_TIME=
while true # loop forever
do
# контроль интернет потока
# подробности здесь http://mpd.wikia.com/wiki/Hack:stream-monitor
TIME="0"
STATE="UNKNOWN"
RESP=`echo -e "status\\nclose" | nc localhost 6600 `
IFS=": "
while read KEY VALUE; do
case "$KEY" in
state) STATE="$VALUE";;
time) TIME="$VALUE";;
esac
done <<<"$RESP"
unset IFS
if [ "$STATE" == "play" ]; then
if [ "$TIME" = "$OLD_TIME" ]; then
mpc stop; mpc play
sleep 1
continue
fi
fi
OLD_TIME=$TIME
# get name of current song from the mpd server
sErr=$(mpc 2>&1)
nErr=$?
sErr=$(echo "$sErr" | grep -i "error:")
if [[ $nErr -ne 0 || -n $sErr ]]
then # have error
if [ $nErr -ne 0 ]
then
if [ -z sErr ]
then
sErr="error:0. Nameless sound device error"
else # have error code and have message
sErr=$(echo $sErr | sed -r 's/^[eE][rR][Rr][oO][rR]:/error:1. /')
fi
else
sErr=$(echo $sErr | sed -r 's/^[eE][rR][Rr][oO][rR]:/error:2. /')
fi
sErr=$(echo ${sErr:0:59})
echo $sErr > /dev/ttyATH0 # sent error message to arduino
echo $sErr # send it on console for debug
mpc stop; mpc play
sleep 1 # free CPU for another process work
continue
fi
sErr=$(echo "status" | nc localhost 6600 | grep -i "error:" |\
sed -r 's/[eE][rR][Rr][oO][rR]:/error:3. /')
if [[ -n $sErr ]]
then
echo $sErr > /dev/ttyATH0
echo $sErr
mpc stop; mpc play
sleep 1
continue
fi
#if state is not playing, then wrote message about error
if ! mpc | grep -q '\[playing\]'
then
sErr="error:4. mpd do not playing."
echo $sErr > /dev/ttyATH0
echo $sErr
mpc stop; mpc play
sleep 1
continue
fi
number=$(echo "currentsong" | nc localhost 6600 | awk '$1=="Pos:" {print x$2}')
echo "play:$[$number+1]. ${vName[$number]}" > /dev/ttyATH0 # send it to the AVR for display
# echo "play:$[$number+1]. ${vName[$number]}" # send it to console for debug
sleep 1 # wait a while, this determines the base rate at which
# the AVR display loops
done
Файл SendToTTY.sh
#!/bin/bash
#**********************************************************************************
#* скрипт SendToTTY.sh - это bash программа для реализации wifi радио, *
#* она посылает число доступных станций в arduino *
#* 30.01.2014 zepete.livejournal.com *
#**********************************************************************************
source '/root/station-list.sh'
while true
do
echo "TPL may play $STATIONS channal." > /dev/ttyATH0
sleep 3
doneФайл time.sh#!/bin/ash
#**********************************************************************************
#* скрипт time.sh - это bash программа для реализации wifi радио, *
#* посылает в arduino раз в минуту текущее время. *
#* 30.01.2014 zepete.livejournal.com *
#**********************************************************************************
while true # loop forever
do
variable=$(date +%a\ %e.%m.%y\ %H:%M)
echo time:$variable > /dev/ttyATH0
sleep 60
done
Файл station-list.sh
#!/bin/bash
#**************************************************************************************
#* скрипт time.sh - это bash программа для реализации wifi радио, содержит константы: *
#* STATIONS - число доступных станций; *
#* vName - отображаемое имя станции; *
#* vAddr - адрес аудиопотока *
#* 09.02.2014 zepete.livejournal.com *
#**************************************************************************************
declare -r -i STATIONS=45
declare -a vName
declare -a vAddr
vName[0]='radio shanson'
vAddr[0]='http://dc.san.ru:8000/shanson'
vName[1]='radio rossii'
vAddr[1]='http://81.19.85.195:80/rrusia64.mp3'
vName[2]='russkoe radio'
vAddr[2]='http://rr.fmtuner.ru/;stream.mp3'
vName[3]='ermitazh'
vAddr[3]='http://91.190.117.131:8000/live'
vName[4]='Classic FM'
vAddr[4]='http://media-ice.musicradio.com:80/ClassicFMMP3'
vName[5]='radio svoboda'
vAddr[5]='http://svobodanews.fvds.ru:8000/Test_RFERL_stream'
vName[6]='radonezh'
vAddr[6]='http://195.151.189.25/RAD.mp3'
vName[7]='podmoskovnye vechera'
vAddr[7]='http://setmedia.ru:8000/high5'
vName[8]='ZaycevFM'
vAddr[8]='http://radio.zaycev.fm:9002/alternative/ZaycevFM(128)'
vName[9]='detskoe radio'
vAddr[9]='http://79.143.70.114:8000/detifm-dvbs-64k.mp3'
vName[10]='my radio: detskie pesni'
vAddr[10]='http://music.myradio.ua:8000/kids-songs128.mp3'
vName[11]='detskij mir'
vAddr[11]='http://icecast.etvnet.com:8000/kids128.mp3'
vName[12]='bob jazz'
vAddr[12]='http://stream01.radiocon.ru:8000/bobjazz'
vName[13]='intervolna'
vAddr[13]='http://intervolna.com:8000/Inter'
vName[14]='La Femme Radio'
vAddr[14]='http://live.rzs.ru/lf.128.mp3'
vName[15]='my radio: jazz'
vAddr[15]='http://music.myradio.ua:8000/Jazz128.mp3'
vName[16]='swiss classic'
vAddr[16]='http://stream.srg-ssr.ch/m/rsc_de/mp3_128'
vName[17]='Radio Classique'
vAddr[17]='http://broadcast.infomaniak.net:80/radioclassique-high.mp3'
vName[18]='Baroko radio'
vAddr[18]='http://streaming208.radionomy.com/Barock-Music?group=0&countrycode=RU&similarprocess=0&crashed=0'
vName[19]='hit fm'
vAddr[19]='http://hit.fmtuner.ru/;stream.mp3'
vName[20]='Alla'
vAddr[20]='http://radio-alla.com:8000/listen64'
vName[21]='militsejskaya volna'
vAddr[21]='http://mv101-1.ru:8000/mv'
vName[22]='Eurovision Song Contest Radio'
vAddr[22]='http://stream.escradio.com:8030/;stream.mp3'
vName[23]='vanya'
vAddr[23]='http://panel.radio-box.org:8001/rv'
vName[24]='business fm'
vAddr[24]='http://bfmstream.bfm.ru:8004/fm'
vName[25]='russkaya sluzhba novostej'
vAddr[25]='http://stream02.media.rambler.ru/rsn96.mp3'
vName[26]='komsomolskay pravda'
vAddr[26]='http://radio.kp.ru:8000/64'
vName[27]='mayak'
vAddr[27]='http://stream01.media.rambler.ru/mayak64.mp3'
vName[28]='moskva fm'
vAddr[28]='http://bcast.krc.ru:8000/gm-fm-128'
vName[29]='eho moskvy'
vAddr[29]='http://81.19.85.197/echo.mp3?53&59'
vName[30]='kommersant'
vAddr[30]='http://81.19.85.195/komm128.mp3'
vName[31]='narodnoe radio'
vAddr[31]='http://213.85.130.203:8080/stream.mp3'
vName[32]='grad petrov'
vAddr[32]='http://www.grad-petrov.ru:8093/mp3-40'
vName[33]='vera'
vAddr[33]='http://radiovera.hostingradio.ru:8007/radiovera_64'
vName[34]='glagol'
vAddr[34]='http://s4.radioheart.ru:8007/radio_glagol'
vName[35]='kabriolet'
vAddr[35]='http://setmedia.ru:8000/high3'
vName[36]='volshebnyj shanson'
vAddr[36]='http://listen2.myradio24.com:9000/8144'
vName[37]='eTVnet shanson'
vAddr[37]='http://icecast.etvnet.com:8000/shanson128.mp3'
vName[38]='karnaval'
vAddr[38]='http://online.carnivalfm.ru:8000/stream/2/;stream.mp3'
vName[39]='nostalzi'
vAddr[39]='http://78.159.239.4:8800/'
vName[40]='zolotoj vek'
vAddr[40]='http://setmedia.ru:8000/high'
vName[41]='diskoteka 80'
vAddr[41]='http://stream04.media.rambler.ru/disco128.mp3'
vName[42]='All hits 70s'
vAddr[42]='http://pub3.sky.fm/sky_hit70s'
vName[43]='yumor fm'
vAddr[43]='http://stream01.media.rambler.ru/umor128.mp3'
vName[44]='Comedy radio'
vAddr[44]='http://comedy.hostingradio.ru:8012/comedy'
declare -r vName
declare -r vAddr