понедельник, 23 августа 2010 г.

flac & cue в mp3

Иногда попадаются рипы компакт-дисков, сделанные аудиофилами. Аудиофилам обычно очень важно, чтобы рип представлял собой точную копию компакт-диска, поэтому они часто делают рипы всего диска в виде одного файла формате flac, который они сопровождают ещё и файлом со списком дорожек в формате cue.

Чтобы закачать такую музыку на аудио-плеер, умеющий воспроизводить только mp3 или ogg, приходится разбивать flac на отдельные mp3-треки.

Кроме разбивки flac-файла на отдельные файлы и преобразования каждого из файлов в формат mp3 полезно также перенести всю полезную информацию из cue-файла в теги mp3-файла. Для этого нам понадобятся следующие пакеты: shntool, cuetools, lame, enca. Установим их:
# apt-get install shntool cuetools lame enca
shntool потребуется для того, чтобы разбить flac-файл на отдельные wav-файлы, cuetools понадобится для извлечения полезной информации из cue-файла, lame - для кодирования wav-файлов в формат mp3 и простановки тегов, enca используется для автоматического определения кодировки текста в cue-файле (поскольку cue-файл мог быть создан как в Windows, так и в Linux и может иметь символы самых разных алфавитов).

Теперь можно попытаться соединить всё это в единый скрипт:
#!/bin/sh

FROMCP=`enca -e *.cue`
iconv -f $FROMCP -t UTF-8 *.cue > /tmp/list.cue

DATE=`grep "REM DATE" /tmp/list.cue | sed -e 's/REM DATE \(.*\)/\1/g'`
GENRE=`grep "REM GENRE" /tmp/list.cue | sed -e 's/REM GENRE \(.*\)/\1/g'`
COMMENT=`grep "REM COMMENT" /tmp/list.cue | sed -e 's/REM COMMENT \(.*\)/\1/g'`
NUMBER=`cueprint -d "%N" /tmp/list.cue`

shntool split -f /tmp/list.cue *.flac -t %n

for((I=1;I<=NUMBER;I++));
do
  cueprint -n $I -t "ARTIST=\"%p\"\nALBUM=\"%T\"\nTRACKNUMBER=\"%n\"\nTITLE=\"%t\"\n" /tmp/list.cue > /tmp/tags
  . /tmp/tags
  J=`printf "%02d" $I`
  lame -b 192 --cbr \
    --ty "$DATE" \
    --tg "$GENRE" \
    --tc "$COMMENT" \
    --ta "$ARTIST" \
    --tl "$ALBUM" \
    --tn "$TRACKNUMBER" \
    --tt "$TITLE" \
    --add-id3v2 \
    --id3v2-only \
    $J.wav $J.mp3
  rm $J.wav
done

rm /tmp/list.cue /tmp/tags
Скрипт рассчитан на то, что в текущем каталоге имеется только один cue-файл и один flac-файл.

Иногда вместо flac используется ape, который с лицензионной стороны намного хуже flac'а. В частности, существовавший когда-то на просторах опенсорса проект mac (Monkey's Audio Codec), исчез именно из-за лицензионных проблем. Не смотря на это, кое-где ещё можно найти как исходники, так и deb-пакет. После установки пакета shntool можно использовать прежним образом, единственное отличие будет заключаться лишь в том, что вместо flac-файла нужно будет указать ape-файл.

Обновлено 3 сентября 2010 года. При обновлении этой заметки и скрипта был использован комментарий к моей старой заметке Конвертируем FLAC в MP3 под Debian.

суббота, 21 августа 2010 г.

Duke Nukem 3D в Debian GNU/Linux

Продолжаю серию заметок о запуске старых игр - стрелялок от первого лица:
  1. Quake в Linux
  2. Запуск Quake на движке Nexuiz
  3. Quake2 на Debian GNU/Linux
На этот раз я откопал современный порт Duke Nukem 3D, который называется Eduke32. Официальный сайт проекта находится по следующему адресу: http://www.eduke32.com/ Для установки движка игры воспользуемся репозиторием Debian на сайте проекта. На странице Apt Repository находим интересующий нас раздел Lenny. В соответствии с инструкциями добавляем репозиторий в систему, прописав следующие две строчки в файл /etc/apt/sources.list:
deb http://apt.duke4.net lenny main
deb-src http://apt.duke4.net lenny main
Теперь добавим PGP-ключ репозитория с помощью следующей команды:
# wget http://apt.duke4.net/key/eduke32.gpg -O- | apt-key add -
Обновим список пакетов:
# apt-get update
И установим интересующие нас пакеты с движком игры и с условно-бесплатной версией самой игры:
# apt-get install eduke32 duke3d-shareware
Кроме этих двух пакетов в репозитории имеются ещё два пакета: build-engine-utils - коллекция инструментов, предназначенных для манипуляции данными игр, основанных на движке Build (из таковых я припоминаю ещё игры Blood, Redneck Rampage и Outlaws) и mapster32 - редактор карт, работающий в режиме OpenGL. В общем, в этом репозитории, похоже, есть всё необходимое, чтобы делать новые карты и модификации игры.

Но это ещё не всё. Ещё я нашёл проект High Resolution Pack, в рамках которого люди занимаются повышением разрешения текстур и заменой всех спрайтов на модели: polymer_hrp132.zip, архивчик уже достиг объёма 466 мегабайт!

Скачаем последний релиз HRP и распакуем его в каталог с настройками личными игры текущего пользователя:
$ wget http://www.duke4.org/files/nightfright/beta/polymer_hrp132.zip
$ unzip polymer_hrp132.zip -d ~/.eduke32
Теперь при запуске игры, в окошке выбора разрешения нужно указать использование движка Polymer, который как раз и умеет рисовать трёхмерные модели.

Вот так игра выглядит на разрешении 1280x1024 без использования HRP:

А вот так выглядит на разрешении 800x600 с использованием HRP:

Ещё пара снимков с использованием HRP. Этот с разрешением 1280x1024:

Этот с разрешением 800x600:

Имеются, однако, и недостатки - игра довольно сильно тормозит, требует много ресурсов (на моём компьютере игра отъела полгигабайта памяти в режиме без HRP), отчего иногда замораживается секунд на 5-10 и иногда падает. Если хотите поиграть в игру полноценно, советую найти полную, не условно-бесплатную версию файла ресурсов и уменьшить настройки качества картинки.

пятница, 13 августа 2010 г.

Lighttpd и gamin

Ранее я уже писал, что начал пользоваться Mathopd: Биография одного домашнего сервера и настройка Mathopd. Тогда я решил попробовать его, потому что привычный Lighttpd отказывался устанавливаться в отсутствии famd, а famd конфликтовал с gamin, который я установил, чтобы избежать внезапных зависаний программ: famd vs gamin. Нужно было пересобрать Lighttpd с gamin вместо famd, но мне тогда было лень этим заниматься, т.к. это было прекрасным поводом попробовать Mathopd :)

На днях Mathopd мне наконец надоел и я решил всё-таки собрать Lighttpd с gamin. Рецептом сборки этой связки я и хочу поделиться.

Для начала, скачаем исходники:
$ apt-get source lighttpd
И перейдём в каталог с распакованными исходниками и информацией для сборки:
$ cd lighttpd-1.4.19
Затем, заглянем в файл debian/control и просмотрим список зависимостей для сборки пакета (Build-Depends): debhelper (>= 5.0.0), cdbs, mime-support, libssl-dev, zlib1g-dev, libbz2-dev, libattr1-dev, libpcre3-dev, libmysqlclient15-dev, libfam-dev, libldap2-dev, libfcgi-dev, libgdbm-dev, libmemcache-dev, liblua5.1-0-dev, quilt, patchutils, pkg-config, uuid-dev, libsqlite3-dev, libxml2-dev, libkrb5-dev, perl

Установим всё это хозяйство, за исключением libfam-dev, который мы заменим на libgamin-dev:
# apt-get install debhelper cdbs mime-support libssl-dev zlib1g-dev libbz2-dev \
  libattr1-dev libpcre3-dev libmysqlclient15-dev libgamin-dev libldap2-dev libfcgi-dev \
  libgdbm-dev libmemcache-dev liblua5.1-0-dev quilt patchutils pkg-config uuid-dev \
  libsqlite3-dev libxml2-dev libkrb5-dev perl
Теперь отредактируем файл debian/control, заменив в нём libfam-dev на libgamin-dev.

Далее, опишем изменения, сделанные в пакете с помощью dch:
$ dch -i
Я внёс следующее описание сделанных изменений:
lighttpd (1.4.19-5+lenny1gamin) stable-security; urgency=low

* Changed dependency from libfam-dev to libgamin-dev.

-- Vladimir Stupin <wheelof@gmail.com>  Fri, 13 Aug 2010 10:17:22 +0600

Осталось лишь собрать изменённый пакет:
$ dpkg-buildpackage -b -us -uc -rfakeroot
Всё. Переходим в каталог выше, где и находятся собранные пакеты:
lighttpd_1.4.19-5+lenny1gamin_i386.deb
lighttpd-doc_1.4.19-5+lenny1gamin_all.deb
lighttpd-mod-cml_1.4.19-5+lenny1gamin_i386.deb
lighttpd-mod-magnet_1.4.19-5+lenny1gamin_i386.deb
lighttpd-mod-mysql-vhost_1.4.19-5+lenny1gamin_i386.deb
lighttpd-mod-trigger-b4-dl_1.4.19-5+lenny1gamin_i386.deb
lighttpd-mod-webdav_1.4.19-5+lenny1gamin_i386.deb
Устанавливаем нужные пакеты с помощью dpkg и пользуемся:
# dpkg -i lighttpd_1.4.19-5+lenny1gamin_i386.deb

среда, 4 августа 2010 г.

Доступ к буферу обмена X Window System из командной строки с помощью xclip

Перевод статьи: Access the X Window System Clipboard from the Command Line with xclip

17 марта 2009, Эрик Фэлор (Erik Falor)

Вы когда-нибудь выделяли текст в окне терминала, чтобы скопировать его в X-приложение? Отбросьте мышь и воспользуйтесь вместо неё xclip. С помощью xclip вы просто перенаправляете через конвейер в xclip тот текст, который вы хотите скопировать:
$ lspci | xclip
Теперь перейдите в X-приложение и вставьте захваченный вывод в программу. xclip также позволит вам “вставить” выбранный текст в терминал. Просто воспользуйтесь опцией -o для вывода выделенного текста:
$ xclip -o
xclip можно найти на sourceforge.net/projects/xclip.

Изменение громкости из сценария Bash

Перевод статьи: Change Volume From a Bash Script

24 сентября 2008, Митч Фрэзер (Mitch Frazier)

Если вы пользуетесь звуковой системой ALSA, вы можете воспользоваться функциями, содержащимися в представленном сценарии, для получения и установки громкости звука вашей системы. Вы можете использовать его, если у вас запущен сторожевой сценарий и вы хотите увеличить громкость сигнала во время тревоги, а затем вернуть громкость обратно к предыдущему уровню.

Функция get просто использует amixer для вывода информации о канале управления миксером "Master" и затем использует grep для вырезания нужного значения из выведенной информации.

Функция set также использует amixer для задания громкости. Она использует опцию "cset" программы amixer.

Сценарий следующий:
#!/bin/bash
#

#####################################################################
# Получить текущую громкость.
function get_volume()
{
  mixer=$(amixer get Master | grep 'Front Left:')
  echo $mixer | cut -d ' ' -f 4
}

#####################################################################
# Задать громкость.
function set_volume()
{
  amixer cset iface=MIXER,name="Master Playback Volume" $1 >/dev/null
}

if [[ $(basename $0 .sh) == 'sound' ]]; then
  sound_file=~/Documents/sounds/notify.wav
  if [[ "$1" ]]; then
    sound_file="$1";
  fi

  ovol=$(get_volume)
  echo "Текущая громкость: $ovol"
  aplay $sound_file
  sleep 2

  vol=40
  echo "Воспроизведение на громкости: $vol"
  set_volume $vol
  aplay $sound_file
  sleep 2

  echo "Возвращение к громкости: $ovol"
  set_volume $ovol
  aplay $sound_file
fi

# vim: tabstop=4: shiftwidth=4: noexpandtab:
# kate: tab-width 4; indent-width 4; replace-tabs false;
Если вы сохраните этот сценарий под именем sound.sh и запустите его самого, передав имя звукового файла, сценарий воспроизведёт файл на текущей громкости, затем поднимет громкость и воспроизведёт его снова, и наконец, восстановит громкость и воспроизведёт его последний раз. Если вы откроете средство управления миксером перед запуском сценария, вы должны увидеть как громкость главного канала изменяется под действием сценария. Вы можете изменить значение громкости в строке vol=40 на значение, которое вам нужно.


Митч Фрэзер (Mitch Frazier) является помощником редактора в Linux Journal и веб-редактором в linuxjournal.com.

Скачать весь веб-сайт с помощью wget

Перевод статьи: Downloading an Entire Web Site with wget

05 сентября 2008, Дашамир Хоксха (Dashamir Hoxha)

Если вам когда-нибудь потребуется скачать целый веб-сайт, например для просмотра без доступа в интернет, wget может это сделать -- например:
$ wget \
  --recursive \
  --no-clobber \
  --page-requisites \
  --html-extension \
  --convert-links \
  --restrict-file-names=windows \
  --domains website.org \
  --no-parent \
  www.website.org/tutorials/html/
Эта команда скачает веб-сайт www.website.org/tutorials/html/.

Используются следующие опции:
  • --recursive: скачивать весь веб-сайт.
  • --domains website.org: не переходить по ссылкам вне сайта website.org.
  • --no-parent: не переходить по ссылкам вне каталога tutorials/html/.
  • --page-requisites: собрать все элементы, относящиеся к странице (изображения, CSS и так далее).
  • --html-extension: сохранять файлы с расширением .html.
  • --convert-links: преобразовывать ссылки так, чтобы они работали локально, без доступа в интернет.
  • --restrict-file-names=windows: изменять имена файлов таким образом, чтобы они работали в Windows.
  • --no-clobber: не заменять какие-либо существующие файлы (используется в случае, если скачивание было прервано и возобновлено).

Наслаждайтесь Gawk

Перевод статьи: Fun With Gawk

15 февраля 2010, Джеймс Хайннэнт (James Hinnant)

Когда grep и sed бывает недостаточно, gawk может предоставить дополнительную лошадиную силу, которая вам необходима. Следующий совет содержит образец того, что можно делать с помощью gawk.

Выделить последний столбец из текстового файла, столбцы которого разделены пробелами:
$ cat myfile | gawk '{print $NF}'
или:
$ gawk '{print $NF}' myfile
Вывести количества файлов, которыми владеет каждый из пользователей в текущем каталоге:
$ /bin/ls -l | \
  gawk 'NR > 1 {counts[$3]++;}
END {for (s in counts) {
printf(" %-15s : % 5d\n",
s, counts[s]);}}' | \
  sort
Завершить ваши процессы (одно из применений - завершить зависший сеанс, если вы можете удалённо войти на рабочую станцию с другого компьютера):
$ ps -elf | \
  gawk -v me="$USER" '$3 == me {print $4}' | \
  egrep -v $$ | \
  xargs -i@@ kill -9 @@; kill -9 $$

Преобразовать имена файлов к нижнему регистру

Перевод статьи: Convert Filenames to Lowercase

25 июля 2008, Фил Хьюз (Phil Hughes)

Я собирался сказать, что я написал это вчера, но отметка времени файла указывает на то, что это было 22 ноября 1998. Ничего нового, ничего особенного, это просто работает.

Вернёмся в старое-доброе время операционных систем, не понимавших разницы между NAME и name. В результате, если иногда приходится копировать файлы с гибких дисков (помните такие?), созданных на Давно Онемевшей Системе, можно получить свалку каталогов с именами файлов в верхнем регистре. Поскольку мы, опытные старожилы UNIX, пользуемся хитрой уловкой для вывода имён каталогов до имён файлов файлов по команде ls (а именно - начинаем имена каталогов с букв в верхнем регистре), наличие имён файлов с символами в верхнем регистре нас раздражает.

Поскольку я слишком часто пользовался командой mv и ввод команд типа mv FILE.TXT file.txt меня окончательно изнурил, я написал этот сценарий. Я думал, что я просто сделал косметический ремонт, но на самом деле сценарий делает работу и в нём легко разобраться. (Номера строк приведены просто для того, чтобы на них ссылаться.)
1   #!/bin/sh
 2   # lowerit
 3   # преобразовывает имена всех файлов в текущем каталоге к нижнему регистру
 4   # работает только над обычными файлами -- не меняет имена каталогов
 5   # запрашивает подтверждение перед заменой существующего файла
 6   for x in `ls`
 7   do
 8     if [ ! -f $x ]; then
 9       continue
10     fi
11     lc=`echo $x | tr '[A-Z]' '[a-z]'`
12     if [ $lc != $x ]; then
13       mv -i $x $lc
14     fi
15   done
Строка 6 начинает цикл (который заканчивается в строке 15). Команда ls возвращает список имён файлов, которые последовательно назначаются переменной оболочки x. if test (строки с 8 по 10) проверяет, является ли имя текущего файла именем простого файла. Если нет, остаток выражения в текущего прохода цикла пропускается.

Если выполняется строка 11, то известно, что обрабатывается обычный файл. С помощью tr мы приводим имя файла в нижний регистр и присваиваем новое имя переменной оболочки lc. Затем в строке 12 происходит проверка, что имя файла в нижнем регистре отличается от исходного. Если это так, то выполняется 13 строка, которая меняет исходное имя файла на новое имя в нижнем регистре. Опция -i заставляет mv спрашивать подтверждение, если команда собирается перезаписать существующий файл.

Фил Хьюз (Phil Hughes)

Дополнение переводчика от 13-05-2012. Нашёл ещё один вариант скрипта для этой задачи:
$ find ./ -type f | awk '{ print $1 " " tolower($1) }' | xargs -L 1 mv

Проверка правильности IP-адресов из сценария Bash

Перевод статьи: Validating an IP Address in a Bash Script

26 июня 2008, Митч Фрэзер (Mitch Frazier)

Я часто пишу об использовании массивов bash и о регулярных выражениях bash, поэтому решил привести более полезный пример их использования для проверки правильности IP-адресов.

Задача очевидна: IP-адреса являются 32-битными значениями, записанными как четыре числа (отдельные байты IP-адреса), разделённых точками. Каждое из четырёх чисел может принимать значение в диапазоне от 0 до 255.

Следующий сценарий bash содержит функцию, которая возвращает истину, если её передан правильный IP-адрес и ложь в противном случае. В bash под истиной понимают завершение с нулевым кодом, всё остальное означает ложь. Код команды/функции bash помещается в переменную "$?".
#!/bin/bash

# Проверка правильности IP-адреса:
# Способ применения:
#      valid_ip IP_АДРЕС
#      if [[ $? -eq 0 ]]; then echo good; else echo bad; fi
#   ИЛИ
#      if valid_ip IP_ADDRESS; then echo good; else echo bad; fi
#
function valid_ip()
{
  local ip=$1
  local stat=1

  if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    OIFS=$IFS
    IFS='.'
    ip=($ip)
    IFS=$OIFS
    [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
      && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
    stat=$?
  fi
  return $stat
}

# При непосредственном запуске выполним несколько проверок.
if [[ "$(basename $0 .sh)" == 'valid_ip' ]]; then
  ips='
4.2.2.2
a.b.c.d
192.168.1.1
0.0.0.0
255.255.255.255
255.255.255.256
192.168.0.1
192.168.0
1234.123.123.123
'
  for ip in $ips
  do
    if valid_ip $ip; then
      stat='good';
    else
      stat='bad';
    fi
    printf "%-20s: %s\n" "$ip" "$stat"
  done
fi
Если сохранить этот сценарий под именем "valid_ip.sh" и запустить его напрямую, он проведёт несколько проверок и выведет результаты:
# sh valid_ip.sh
4.2.2.2             : good
a.b.c.d             : bad
192.168.1.1         : good
0.0.0.0             : good
255.255.255.255     : good
255.255.255.256     : bad
192.168.0.1         : good
192.168.0           : bad
1234.123.123.123    : bad
В функции valid_ip, чтобы удостовериться в том, что рассматриваемый IP-адрес состоит из четырёх разделённых точками чисел, используется регулярное выражение в операторе if:
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
Если проверка пройдена, код внутри оператора if разделяет рассматриваемый IP-адрес на четыре части по точкам и помещает части в массив:
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
Эти действия меняют переменную bash, которая называется "внутренний разделитель полей" (Internal Field Separator). Обычно она используется для обработки слов, разделённых пробелами, по после этого bash будет использовать для разделения полей точки. Поместим значение рассматриваемого IP-адреса внутрь скобок и присвоим их значение массиву, поместив каждое из полей, разделённых точками, в отдельную ячейку массива. Теперь проверим отдельные поля, чтобы удостовериться в том, что они меньше или равны 255. Результат проверки сохраним, так чтобы его можно было вернуть в качестве значения функции:
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
  && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
Отметим, что не обязательно проводить проверку равно ли число нулю или оно больше нуля, так как проверка регулярным выражением уже отфильтровала всё, что не состоит из точек и цифр.


Митч Фрэзер (Mitch Frazier) является помощником редактора в Linux Journal и веб-редактором в linuxjournal.com.