Сначала просто написал скрипт будильника. Теперь попробую собрать инфу по разным скриптам с использованием синтезатора речи festival в одну тему.
Хотя на самом деле это уже сделано
здесьНу да ладно. Итак начнем.
Установка festival и festvox-ru, исправление багов.Пакеты festival и festvox-ru лежат в стандартных репозиториях UBUNTU Karmic и Lucid. Ставим:
sudo apt-get install festival festvox-ru
Если у вас более ранний дистрибутив, то festvox-ru можно взять
здесь (распаковать в /usr/share/festival/voices/russian/msu_ru_nsh_clunits)
Теперь исправим пару багов:
Обеспечение полноценной поддержки русского языка
(Начиная с версии festival 1.96 лечение этого бага не требуется)
В файл /usr/share/festival/languages.scm дописать вначале:
(define (language_russian)
"(language_russian)
Set up language parameters for Russian."
(set! male1 voice_msu_ru_nsh_clunits)
(male1)
(Parameter.set 'Language 'russian)
)
и в этом же файле в define(select_language language) добавить пару строчек
((equal? language 'russian)
(language_russian))
Обеспечение возможности одновременной работы festival и аудио/видео-плееров
(Начиная с версии festival 1:2.0.95 лечение этого бага не требуется)
В файл /usr/share/festival/festival.scm в конце добавить строки
(Parameter.set 'Audio_Method 'Audio_Command)
(Parameter.set 'Audio_Command "aplay -q -c 1 -t raw -f s16 -r $SR $FILE")
Или этот параметр можно добавить в ~/.festivalrc. Этот файл создается специально для прописи параметров. Но не обязательно, можно сделать, как сказано выше.
На этом подготовка завершена. Приступим непосредственно к написанию скриптов.
Стоп, чуть не забыл. Чтобы не было лишних вопросов, заранее предупрежу (или напомню), скриптам нужно давать право на исполнение.
chmod +x script.sh
Теперь приступим.
БудильникСоздаем скрипт в домашнем каталоге
gedit alarm.sh
#!/bin/bash
#Чтобы поставить будильник, вводим в терминале команду "crontab -e"
#И прописываем нужные параметры:
## m h dom mon dow command
#0 7 * * 1-5 ./alarm.sh
#0 10 * * 6-7 ./alarm.sh
export DISPLAY=:0
export LANG=ru_RU.UTF-8
# Выбираем нужный синтезатор речи, раскомментировав одну из строк:
#sayit () { espeak -vru -s130; }
#sayit () { festival --tts --language russian; }
#sayit () { festival_client --ttw | aplay -q; }
sayit () { RHVoice | aplay -q; }
# Склоняем в соответствующем падеже слова "час" и "минута"
check_date ()
{
HOUR=`date +%H`
MIN=`date +%M`
if [[ "$HOUR" = 1[1234] || "$HOUR" = ?[056789] ]]; then LC_HOUR="часов"
elif [[ "$HOUR" = ?[234] ]]; then LC_HOUR="час+а"
elif [[ "$HOUR" = ?1 ]]; then LC_HOUR="час"
else LC_HOUR="значение не определено"
fi
if [[ "$MIN" = 1[1234] || "$MIN" = ?[056789] ]]; then LC_MINUTE="минут"
elif [[ "$MIN" = ?[34] ]]; then LC_MINUTE="минуты"
else LC_MINUTE="значение не определено"
fi
if [[ "$MIN" = 01 ]]; then TIME="$HOUR $LC_HOUR однa минута"
elif [[ "$MIN" = 11 ]]; then TIME="$HOUR $LC_HOUR $MIN $LC_MINUTE"
elif [[ "$MIN" = ?1 ]]; then TIME="$HOUR $LC_HOUR $(($MIN-1)) одна минута"
elif [[ "$MIN" = 02 ]]; then TIME="$HOUR $LC_HOUR две минуты"
elif [[ "$MIN" = 12 ]]; then TIME="$HOUR $LC_HOUR $MIN $LC_MINUTE"
elif [[ "$MIN" = ?2 ]]; then TIME="$HOUR $LC_HOUR $(($MIN-2)) две минуты"
elif [[ "$MIN" = 00 ]]; then TIME="$HOUR $LC_HOUR ровно"
else TIME="$HOUR $LC_HOUR $MIN $LC_MINUTE"
fi
if [[ "$HOUR" = 08 ]] || [[ "$HOUR" -ge 06 && "$HOUR" -le 11 ]]; then
HELLO="Доброе утро"
elif [[ "$HOUR" -ge 12 && "$HOUR" -le 17 ]]; then
HELLO="Добрый день"
elif [[ "$HOUR" -ge 18 && "$HOUR" -le 23 ]]; then
HELLO="Добрый вечер"
elif [[ "$HOUR" -ge 00 && "$HOUR" -le 05 ]]; then
HELLO="Доброй ночи"
else HELLO="Привет"
fi
}
# Выясняем, в каком городе мы находимся
CITY=`wget -q -O - 2ip.ru | grep -P geoip | sed 's/<[^>]*>//g' | awk '{print $3}'`
CITY_ID=`wget -q -O - http://bar.gismeteo.ru/gmbartlist.xml | iconv -f cp1251 -t utf8 | grep $CITY | awk '{print $3}' | sed 's/[i="]//g'`
TMP_FILE="/tmp/gismeteo_$CITY_ID"
URL="http://www.gismeteo.ru/ztowns/$CITY_ID.htm" #CITY_ID - не тот, к которому привыкли, но перенаправляет, куда надо. Информер: http://informer.gismeteo.ru/xml/$CITY_ID_1.xml
# Получаем температуру в своем городе
wget -q -O - $URL > $TMP_FILE
TEMP="`grep -m 1 'value m_temp c' $TMP_FILE | sed 's/<[^>]*>/ /g' | awk '{print $1}'`"
if [[ `echo $TEMP | grep minus` ]]; then TEMP_SIGN="минус"
else TEMP_SIGN=""
fi
DEGREE="`echo $TEMP | grep -Po '[0-9]{1,2}'`"
# Проверяем погодные условия
WEATH="`grep -m 1 '<dd>' $TMP_FILE | sed 's/[ \t]*//;s/<[^>]*>//g'`"
# Склоняем в соответствующем падеже слово "градус"
if [[ "$DEGREE" = 1[1234] || "$DEGREE" = *[056789] ]]; then LC_DEGREE="градусов"
elif [[ "$DEGREE" = *[234] ]]; then LC_DEGREE="градуса"
elif [[ "$DEGREE" = *1 ]]; then LC_DEGREE="градус"
else LC_DEGREE="значение не определено"
fi
# начальная громкость, в процентах
VOLUME=25
# конечная (максимальная) громкость, в процентах
MAXVOLUME=65
# А теперь сам будильник
amixer -q sset Master $VOLUME% unmute
if [[ `ps h -C rhythmbox` ]]
then sleep 10
else rhythmbox &> /dev/null & sleep 10
fi
rhythmbox-client --set-volume 1.0
playlist="`qdbus --literal org.mpris.MediaPlayer2.rhythmbox /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Playlists.GetPlaylists 1 1 0 0 | sed -e :a -e 's/\][^>]*\]//g;s/\[[^>]*\[ObjectPath: //g'`" #Ищем динамический плейлист "Любимые композиции"
qdbus org.mpris.MediaPlayer2.rhythmbox /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Playlists.ActivatePlaylist $playlist #Запускаем найденный плейлист
rhythmbox-client --next
#rhythmbox-client --play-uri="http://online.radiorecord.ru:8102/tm_128" #Можно и радио послушать
while [[ "$VOLUME" -le "$MAXVOLUME" ]]
do
VOLUME=$(($VOLUME+1))
sleep 1
amixer -q sset Master $VOLUME% unmute
done
sleep 230
rhythmbox-client --set-volume 0.9
sleep 1
rhythmbox-client --set-volume 0.8
sleep 1
rhythmbox-client --set-volume 0.7
sleep 1
rhythmbox-client --set-volume 0.6
sleep 1
rhythmbox-client --set-volume 0.5
sleep 1
rhythmbox-client --set-volume 0.4
check_date
echo "$HELLO, Хозяин" | sayit
echo "Я надеюсь, что вы хорошо спали?" | sayit
echo "Сегодня `date +%A`" | sayit
echo "Время $TIME" | sayit
echo "Температура за окном $TEMP_SIGN $DEGREE $LC_DEGREE, $WEATH" | sayit
echo "Желаю вам удач+нава дня" | sayit
rhythmbox-client --set-volume 0.5
sleep 1
rhythmbox-client --set-volume 0.6
sleep 1
rhythmbox-client --set-volume 0.7
sleep 1
rhythmbox-client --set-volume 0.8
sleep 1
rhythmbox-client --set-volume 0.9
sleep 1
rhythmbox-client --set-volume 1.0
exit 0
Пришлось нарушить правила русского языка ради более-менее нормального звочания festival
Чтобы поставить будильник, вводим в терминале команду "crontab -e".
Должен запускаться консольный текстовый редактор. Но в первый раз система спрашивает, какой именно редактор вам больше по душе: ed, nano или vim.tiny. Если не знаете, выбирайте nano (нужно нажать "2").
В редакторе прописываем нужные параметры:
PATH=/sbin:/bin:/usr/sbin:/usr/bin
SHELL=/bin/bash
# m h dom mon dow command
0 7 * * 1-5 ./alarm.sh
0 10 * * 6-7 ./alarm.sh
Указываем нужное время, у меня в будние дни будильник срабатывает в 7:00, а в выходные в 10:00.
Сохраняем (Ctrl+O), сохраняем как будет предложено. И выходим из редактора (Ctrl+X).
Если манипуляции в терминале оказались (или показались) сложными, то можно запланировать время работы будильника, воспользовавшись gui для cron - gnome-schedule.
При срабатывании будильника сначала включается плеер, какое-то время играет музыка, потом громкость снижается, и электронный голос приветствует и сообщает нам инфу по сегодняшнему дню, время, день, температура за окном. Затем снова играет плеер.
Озвучка открытия/закрытия крышки ноутбукаОткрываем для редактирования файл /etc/acpi/lid.sh, для этого набираем в терминале:
sudo gedit /etc/acpi/lid.sh
Добавляем в этот файл перед строкой
test -f /usr/share/acpi-support/state-funcs || exit 0
следующий текст:
grep -q closed /proc/acpi/button/lid/LID/state
if [ $? = 0 ]
then
echo "Зачем вы меня закрыли?" | festival --tts --language russian;
else
echo "Привет!" | festival --tts --language russian;
fi
Ну или можно вписать стандартные фразы типа "открыто/закрыто".
Соответственно что напишете, то и будет говорить ноутбук при открытии/закрытии крышки.
Проверка почты gmailСоздаем скрипт в домашнем каталоге
gedit gmail
#!/bin/bash
#Чтобы запустить автоматическую проверку почты, вводим в терминале команду "crontab -e"
#И прописываем нужные параметры:
##PATH=/sbin:/bin:/usr/sbin:/usr/bin
##SHELL=/bin/bash
### m h dom mon dow command
##*/15 17-23 * * 1-5 bash gmail
##*/15 10-23 * * 6-7 bash gmail
export DISPLAY=:0
export LANG=ru_RU.UTF-8
#Проверяем почту
NUMB=`wget --secure-protocol=TLSv1 --timeout=3 -t 1 -q -O - https://login:password@mail.google.com/mail/feed/atom --no-check-certificate | grep 'fullcount' | sed "s/<fullcount>\(.*\)<\/fullcount>/\1/"` # или NUMB=`curl -u login:password --silent "https://mail.google.com/mail/feed/atom" | grep 'fullcount' | sed "s/<fullcount>\(.*\)<\/fullcount>/\1/"`
#Склоняем в соответствующем падеже слова "непрочитанные сообщения"
TEMP_NUMB="`echo $NUMB | colrm 1 1`"
if [ "$NUMB" -eq "0" ] || [ "$NUMB" -eq "5" ] || [ "$NUMB" -eq "6" ] || [ "$NUMB" -eq "7" ] || [ "$NUMB" -eq "8" ] || [ "$NUMB" -eq "9" ] || [ "$NUMB" -eq "11" ] || [ "$NUMB" -eq "12" ] || [ "$NUMB" -eq "13" ] || [ "$NUMB" -eq "14" ] || [ "$TEMP_NUMB" -eq "0" ] || [ "$TEMP_NUMB" -eq "5" ] || [ "$TEMP_NUMB" -eq "6" ] || [ "$TEMP_NUMB" -eq "7" ] || [ "$TEMP_NUMB" -eq "8" ] || [ "$TEMP_NUMB" -eq "9" ]; then MSG="непрочитанных сообщений"
elif [ "$NUMB" -eq "2" ] || [ "$NUMB" -eq "3" ] || [ "$NUMB" -eq "4" ] || [ "$TEMP_NUMB" -eq "2" ] || [ "$TEMP_NUMB" -eq "3" ] || [ "$TEMP_NUMB" -eq "4" ]; then MSG="непрочитанных сообщения"
fi
if [ "$NUMB" -eq "1" ]; then NUMB_MSG="одно непрочитанное сообщение"
elif [ "$NUMB" -eq "11" ]; then NUMB_MSG="`echo $NUMB $MSG`"
elif [ "$TEMP_NUMB" -eq "1" ]; then NUMB_MSG="$(echo $NUMB-1|bc), одно непрочитанное сообщение"
else NUMB_MSG="`echo $NUMB $MSG`"
fi
#Проверяем плееры (требования: VLC - в настройках должен быть включен "Интерфейс управления D-Bus"; totem - должен быть включен модуль "Служба D-Bus")
if [ "`dbus-send --dest=org.mpris.Totem --print-reply --type=method_call /Player org.freedesktop.MediaPlayer.GetStatus | sed -n 3p`" == " int32 0" ];
then TOTEM_STATUS=1 # totem вкючен и играет
else TOTEM_STATUS=0 # totem выкючен или стоит на паузе
fi
if [ "`dbus-send --dest=org.mpris.vlc --print-reply --type=method_call /Player org.freedesktop.MediaPlayer.GetStatus | sed -n 3p`" == " int32 0" ];
then VLC_STATUS=1 # VLC вкючен и играет
else VLC_STATUS=0 # VLC выкючен или стоит на паузе
fi
if [[ `ps h -C rhythmbox` ]] && [ "`dbus-send --dest=org.gnome.Rhythmbox --print-reply --type=method_call /org/gnome/Rhythmbox/Player org.gnome.Rhythmbox.Player.getPlaying | sed -n 2p`" == " boolean true" ];
then RHYTHM_STATUS=1 # rhythmbox вкючен и играет
else RHYTHM_STATUS=0 # rhythmbox выкючен или стоит на паузе
fi
#Сообщение
if [ $NUMB -ne "0" ]; then :
if [ $TOTEM_STATUS -eq 1 ]; then dbus-send --dest=org.mpris.Totem --type=method_call /Player org.freedesktop.MediaPlayer.Pause # или просто 'totem --pause'
fi
if [ $VLC_STATUS -eq 1 ]; then dbus-send --dest=org.mpris.vlc --type=method_call /Player org.freedesktop.MediaPlayer.Pause
fi
if [ $RHYTHM_STATUS -eq 1 ]; then dbus-send --dest=org.gnome.Rhythmbox --type=method_call /org/gnome/Rhythmbox/Player org.gnome.Rhythmbox.Player.playPause boolean:false # или просто 'rhythmbox-client --pause'
fi
echo "Хозяин, на вашем почтовом ящике имеется $NUMB_MSG." | festival --tts --language russian
sleep 1
if [ $TOTEM_STATUS -eq 1 ]; then dbus-send --dest=org.mpris.Totem --type=method_call /Player org.freedesktop.MediaPlayer.Pause # или просто 'totem --play'
fi
if [ $VLC_STATUS -eq 1 ]; then dbus-send --dest=org.mpris.vlc --type=method_call /Player org.freedesktop.MediaPlayer.Pause
fi
if [ $RHYTHM_STATUS -eq 1 ]; then dbus-send --dest=org.gnome.Rhythmbox --type=method_call /org/gnome/Rhythmbox/Player org.gnome.Rhythmbox.Player.playPause boolean:false
# или просто 'rhythmbox-client --play'
fi
fi
exit 0
Вместо login:password соответственно вставляем свои логин и пароль. Скрипт также работает для почты @xakep.ru
И снова используем cron, чтобы запланировать автоматическую проверку. Вводим в терминале команду "crontab -e". И прописываем нужные параметры. В моем случае это:
PATH=/sbin:/bin:/usr/sbin:/usr/bin
SHELL=/bin/bash
# m h dom mon dow command
*/15 17-23 * * 1-5 bash gmail
*/15 10-23 * * 6-7 bash gmail
Чтение всплывающих уведомленийНам необходимо создать два скрипта, один из которых мы потом добавим в автоматически-запускаемые приложения в GNOME.
Итак, скрипт первый (speech.sh):
#!/bin/bash
# Добавить в запускаемые приложения: /home/user/run_speech.sh /home/user/speech.sh
COMMAND_COUNTER=0
MESSAGE_HEADER=""
MESSAGE_BODY=""
PARSE_REQUIRED=0
while read -r DBUS_MESSAGE ; do
ID=`echo $DBUS_MESSAGE | grep "member=Notify"`
if [[ $ID ]] ; then
let COMMAND_COUNTER=0
let PARSE_REQUIRED=1
else
if [ $PARSE_REQUIRED -eq 1 ] ; then
ID=`echo $DBUS_MESSAGE | egrep "string\ \""`
if [[ $ID ]] ; then
let COMMAND_COUNTER=$COMMAND_COUNTER+1
fi
if [ $COMMAND_COUNTER -eq 3 ] ; then
MESSAGE_HEADER=`echo $DBUS_MESSAGE | grep "string\ \"" | sed s/^string\ \"//g | sed s/\"$//g`
fi
if [ $COMMAND_COUNTER -eq 4 ] ; then
MESSAGE_BODY=`echo $DBUS_MESSAGE | grep "string\ \"" | sed s/^string\ \"//g | sed s/\"$//g`
echo $MESSAGE_HEADER | festival --tts --language russian
echo $MESSAGE_BODY | festival --tts --language russian
let COMMAND_COUNTER=$COMMAND_COUNTER+1
let PARSE_REQUIRED=0
fi
fi
fi
done
Суть этого скрипта на bash заключается в следующем. Он принимает со стандартного ввода данные, полученные из второго скрипта и затем парсит их. Затем формирует сообщение и отправляет его в festival для синтеза речевого сообщения. Данные для этого скрипта предоставляет второй скрипт (run_speech.sh), который очень короткий и выглядит так:
#!/bin/bash
dbus-monitor "interface='org.freedesktop.Notifications', member='Notify'" | $1
Что делает этот скрипт. Он в качестве параметра принимает название первого скрипта (путь до него должен быть полный) и вызывает утилиту dbus-monitor, которая позволяет увидеть, что передается по шине dbus непосредственно для всплывающих уведомлений. Вывод от dbus-monitor мы передаем на вход нашему первому скрипту.
Далее, добавляем в запускаемые приложения GNOME новую команду (у меня выглядит так):
/home/user/run_speech.sh /home/user/speech.sh
Перезапускаем GNOME и смотрим что получилось. Для проверки можно сделать следующее:
notify-send "Привет" "Я твое новое голосовое сообщение"
Однако, наверняка среди установленных на вашем компьютере приложений найдется программа, всплывающие сообщения которой вы не захотите, чтобы festival озвучивал. В таком случае эту программу можно добавить, так скажем, в "исключения", например, как я это сделал с rhythmbox:
#!/bin/bash
# Добавить в запускаемые приложения: /home/user/run_speech.sh /home/user/speech.sh
COMMAND_COUNTER=0
MESSAGE_HEADER=""
MESSAGE_BODY=""
PARSE_REQUIRED=0
while read -r DBUS_MESSAGE ; do
ID=`echo $DBUS_MESSAGE | grep "member=Notify"`
if [[ $ID ]] ; then
let COMMAND_COUNTER=0
let PARSE_REQUIRED=1
else
if [ $PARSE_REQUIRED -eq 1 ] ; then
ID=`echo $DBUS_MESSAGE | egrep "string\ \""`
if [ "$ID" == 'string "rhythmbox"' ]; then
let COMMAND_COUNTER=5
let PARSE_REQUIRED=0
fi
if [[ $ID ]]; then
let COMMAND_COUNTER=$COMMAND_COUNTER+1
fi
if [ $COMMAND_COUNTER -eq 3 ] ; then
MESSAGE_HEADER=`echo $DBUS_MESSAGE | grep "string\ \"" | sed s/^string\ \"//g | sed s/\"$//g`
fi
if [ $COMMAND_COUNTER -eq 4 ] ; then
MESSAGE_BODY=`echo $DBUS_MESSAGE | grep "string\ \"" | sed s/^string\ \"//g | sed s/\"$//g`
echo $MESSAGE_HEADER | festival --tts --language russian
echo $MESSAGE_BODY | festival --tts --language russian
let COMMAND_COUNTER=$COMMAND_COUNTER+1
let PARSE_REQUIRED=0
fi
fi
fi
done
Озвучка обрыва ppp0 в коньках/by
goldskif &
ratteПрописываем в коньках (~/.conkyrc):
${if_empty ${exec /home/user/eth.sh}} $endif
В папке пользователя создаем файл eth.sh:
#!/bin/sh
LOCKFILE="/tmp/$VAR.lock"
VAR=`sudo ifconfig $1| grep "ppp0"`;
if [ "$VAR" = '' ] ; then
if (! test -f ${LOCKFILE}) then
touch ${LOCKFILE}
echo "человек. обрати внимание, связь потеряна, я нервничаю." | festival --tts --language russian
fi
else
if (test -f ${LOCKFILE}) then
rm ${LOCKFILE}
echo "человек. мы он лайн." | festival --tts --language russian
fi
fi
Озвучка подключения/отключения USB-устройств(В Ubuntu 10.10 возможно работать не будет)
Снова два скрипта.
Первый - /etc/udev/rules.d/62-festival.rules
SUBSYSTEMS=="usb", RUN+="/usr/bin/boltalka.sh %k"
SUBSYSTEMS=="block", RUN+="/usr/bin/boltalka.sh %b"
Второй - /usr/bin/boltalka.sh
#!/bin/bash
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
FESTIVAL="festival --tts"
DEVICE=$1
UDEVINFO="udevadm info"
[ -z "$DEVICE" ] && exit
[ -z "$ACTION" ] && exit
function get_device_attr ()
{
path=`find /sys/devices -name $1`
echo `$UDEVINFO --attribute-walk --path=$path | grep $2 -m1 | cut -f 2 -d '"'`
}
function get_device_name ()
{
device=$1
case $device in
[0-9]-[0-9])
s=`get_device_attr $device "product"`
[ -z "$s" ] && echo "device" || echo "$s"
;;
*)
exit
;;
esac
}
function say ()
{
echo "$1 $2" | $FESTIVAL
exit
}
name=`get_device_name $DEVICE`
if [ -n "$name" ]; then
case "$ACTION" in
add)
say "$name" "was found"
;;
remove)
say "device" "has been removed"
;;
change)
say "$name" "was changed"
;;
esac
fi
Чтобы говорил по-русски, можно сделать, например, так:
(наименование устройства озвучиваться не будет)
#!/bin/bash
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
FESTIVAL="festival --tts --language russian"
DEVICE=$1
UDEVINFO="udevadm info"
[ -z "$DEVICE" ] && exit
[ -z "$ACTION" ] && exit
function get_device_attr ()
{
path=`find /sys/devices -name $1`
echo `$UDEVINFO --attribute-walk --path=$path | grep $2 -m1 | cut -f s16 -d`
}
function get_device_name ()
{
device=$1
case $device in
[0-9]-[0-9])
s=`get_device_attr $device "product"`
[ -z "$s" ] && echo "девайс"
;;
*)
exit
;;
esac
}
function say ()
{
echo "$1 $2" | $FESTIVAL
exit
}
name=`get_device_name $DEVICE`
if [ -n "$name" ]; then
case "$ACTION" in
add)
say "$name" "подключон"
;;
remove)
say "$name" "отключон"
;;
change)
say "$name" "информация изменена"
;;
esac
fi
Благодарности: goldskif,
ratte,
OMUT,
enfernal,
bsod,
КирIk,
Rasskazowhabrahabr.ru,
ru.festivalspeaker.wikia.com,
ubuntuforums.org,
welinux.ru