PC АД PC АД
PC АД

Почта Домой

Музыкальная шкатулка подручными средствами

Нестандартное использование спулера печати

Неумолимо приближается день очередной вечеринки. Чем на этой пати ты собираешься поразить воображение друзей и сердца подруг? Может, новым хранителем экрана? Очередной opengl'ной демкой? Наскоро написанным плагином для gkrellm? К сожалению, всем этим уже никого не удивишь. Тут нужно что-то сногсшибательное, и я попробую тебе помочь. Итак, сегодня на повестке дня тема только для самых настоящих никсанутых гиков - создание своеобразного музыкального автомата с помощью... системы печати. Держись крепче :).

Изюминка шкатулки

Все мы уже привыкли к километровым плейлистам и mp3-плееру, имеющему на борту не один десяток самых разных примочек. Со временем работа с музыкальными файлами превращается в настоящую рутину, но благодаря универсальности UNIX-like операционок и гибкости системы печати BSD можно внести новые идеи в процесс воспроизведения музыки. Собственно, кто нам мешает загружать в буфер печати не обычные документы, а, к примеру, mp3’шки? Не беспокойся, настоящий принтер нам не понадобится. Мы создадим виртуальное устройство печати, извергающее музон через программный фильтр. Все управление прослушиванием будет также осуществляться через систему печати.

Песчинки истории

Изначально система печати System V разрабатывалась без сетевой поддержки и была спроектирована таким образом, что внесение в ее структуру любых изменений становилось крайне сложной задачей для разработчиков. Именно поэтому операционные системы Free/Net/OpenBSD, а также подавляющее большинство Linux дистрибутивов в настоящее время используют систему печати BSD. Демон линейной печати lpd (Line Printer Daemon) представляет собой портированную версию исходного кода, написанного в университете Berkeley для BSD-версии операционной системы UNIX. Помимо одноименного демона, lpd состоит из целого набора программ для управления печатью:

1) lpr - постановка заданий в очередь;

2) lprm - удаление заданий из очереди;

3) lpq - просмотр очереди печати;

4) lpc - обеспечение полного контроля над lpd.

Фильтруем базар

/etc/printcap является главным конфигурационным файлом системы печати BSD. Стоит отметить, что его формат довольно специфичен: первой строкой идут разделенные вертикальной чертой имя, список псевдонимов и описание принтера, затем вся остальная информация в виде "двухсимвольная переменная=значение". Комментарии начинаются с решетки, параметры должны быть разделены между собой двоеточием, а обратный слеш служит для продолжения длинной строки и делает конфиг более наглядным.

Printcap - это особая база данных, содержащая в себе около пятидесяти всевозможных элементов, однако для успешного выполнения нашей миссии мы обойдемся и девятью. Рассмотрим их подробнее:

- переменная lp (:lp=/dev/null:) описывает имя устройства локального принтера. Так как реального принтера у нас нет, то указываем /dev/null.

- переменная sd (:sd=/var/spool/lpd/audio:) определяет каталог спулинга. В идеале у каждого принтера должен быть собственный буфер печати для хранения лочащего, статусного и временных файлов, поэтому вручную создадим каталог, назначив ему соответствующие права доступа:

# mkdir /var/spool/lpd/audio

# chown root:daemon /var/spool/lpd/audio

# chmod 755 /var/spool/lpd/audio

- переменная if (:if=/usr/local/bin/filter:) отвечает за входной фильтр, который по замыслу разработчиков lpd должен выполнять форматирование и преобразование отправленных на печать документов. Именно на этот фильтр мы делаем основную ставку:

# vi /usr/local/bin/filter

#!/bin/sh

/usr/local/bin/mpg123 --aggressive --stereo --8bit - > /dev/null 2>&1

Фильтр возьмет на себя роль посредника. Он будет принимать от пользователя (якобы для печати) задания со стандартного ввода (stdin), воспроизводить mp3-файлы с помощью консольного mp3-плеера (в данном случае mpg123) и посылать все сообщения об ошибках (stderr) на стандартный вывод (stdout).

В качестве альтернативы этому фильтру предложу тебе не менее элегантный вариант с временным файлом, в который со стандартного ввода будут записываться все необходимые для прослушивания композиции. После окончания воспроизведения temp-файл для экономии дискового пространства будет удаляться. Лично мне эта версия скрипта, пусть она и работает немного медленнее, нравится больше:

# vi /usr/local/bin/filter

#!/bin/sh

cat > /tmp/list.m3u

/usr/local/bin/mpg123 --aggressive --stereo --8bit /tmp/list.m3u > /dev/null 2>&1

rm -f /tmp/list.m3u

Далее присваиваем сценарию командного интерпретатора атрибут исполнения:

# chmod +x /usr/local/bin/filter

- с помощью переменной lf (:lf=/var/log/audio.err:) задается файл журналирования сообщений фильтра.

# cp /dev/null /var/log/audio.err

- переменная af (:af=/var/log/audio.acc:) используется для указания лог-файла, в котором учитывается распечатанный пользователем объем информации. Нам эти данные ни к чему, но все же для корректности работы lpd создадим и его:

# cp /dev/null /var/log/audio.acc

- с помощью переменной mx (:mx#0:) можно снять ограничение на максимально допустимый объем файла, посылаемого на печать. Примечание: если значение переменной является числом, то знак равенства заменяется знаком решетки.

- подавление печати заголовков производится с помощью переменной sh (:sh:).

В итоге, собрав по кусочкам все переменные вместе, получаем следующий конфиг для нашего виртуального mp3-принтера:

# vi /etc/printcap

mp3|local audio spooler:\

:lp=/dev/null:\

:sd=/var/spool/lpd/audio:\

:if=/usr/local/bin/filter:\

:lf=/var/log/audio.err:\

:af=/var/log/audio.acc:\

:mx#0:\

:sh:

Рулим спулером печати

Настало время запустить демон системы печати:

# lpd

$ netstat -na | grep 515

tcp 0 0 *.515 *.* LISTEN

В OpenBSD для автоматической загрузки lpd в системном конфигурационном файле /etc/rc.conf необходимо изменить значение директивы lpd_flags с NO на пустые двойные кавычки:

# vi /etc/rc.conf

lpd_flags=""

Пользователи FreeBSD добавляют в /etc/rc.conf следующую запись:

# vi /etc/rc.conf

lpd_enable="YES"

Если у тебя линукс, то в своем дистрибутиве ты без проблем, я надеюсь, найдешь start/stop скрипт для lpd, а затем добавишь его утилитой ntsysv или chkconfig в нужный runlevel.

Далее в "очередь печати" ставим на воспроизведение первый музыкальный файл, передав программе lpr в качестве аргумента имя виртуального принтера:

$ lpr -Pmp3 test.mp3

$ lpq -Pmp3

mp3 is ready and printing

Rank Owner Job Files Total Size

active andrushock 1 test.mp3 7671624 bytes

Удаление поставленных в очередь заданий производится с помощью lprm. Если аргументом выступает идентификатор (берется из вывода lpq, столбец Job), то будет удалено соответствующее задание; если дефис, то все задания пользователя (в случае с суперпользователем - абсолютно все задания); если lprm вызван без аргумента, то текущее задание.

$ lprm -Pmp3

dfA001 dequeued

сfA001 dequeued

По умолчанию lpr/lpq/lprm используют устройство печати lp. Чтобы постоянно не вводить после имени программы "-Pmp3", через переменную окружения PRINTER можно задать имя дополнительного принтера:

$ export PRINTER=mp3

Обнуляется значение ранее объявленной переменной командой unset:

$ unset PRINTER

Клиент всегда прав

Наверное, ни для кого не секрет, что возможность совместного использования ресурсов является одной из сильных сторон *nix-систем, причем общим ресурсом может равнозначно выступать как файл, так и принтер. Так что попробуем разрешить другим компьютерам по сети отправлять музыкальные задания на нашу шкатулку. Для этого в файле /etc/hosts.lpd нужно определить права доступа к локальному демону печати и немного перенастроить /etc/printcap у клиентов.

На www.redhat.com/ в одном из мануалов, посвященных печати в Linux, настоятельно рекомендуется в /etc/hosts.lpd вместо IP-адресов прописывать полные имена хостов, от которых требуется получать задания на печать. Ок, ок, ок. Разработчики дурного не посоветуют, поэтому сначала занесем алиасы клиентов в /etc/hosts (если в сети нет DNS-сервера), и только потом займемся разграничением доступа:

# vi /etc/hosts

192.168.1.1 midian.home.net

192.168.1.2 andrushock.home.net

# vi /etc/hosts.lpd

midian.home.net

На стороне клиента достаточно создать лог-файл для журналирования событий, учетным файлом можно пренебречь:

# cp /dev/null /var/log/audio.err

Клиентский файл /etc/printcap немного отличается от серверного. Кроме пустой директивы lp, каталога сброса и журнального файла, он будет содержать две новые переменные: в записи rm (:rm=192.168.1.2:) мы определим IP-адрес сервера печати, а с помощью rp (:rp=mp3:) укажем удаленный принтер.

# vi /etc/printcap

mp3|remote audio spooler:\

lp=:rm=192.168.1.2:rp=mp3:sd=/var/spool/lpd:lf=/var/log/audio.err:

На клиенте также необходимо загрузить демон системы печати:

# lpd

Все приготовления сделаны, теперь можно переходить непосредственно к тестированию:

$ lpr -Pmp3 /home/ftp/temp/hope.mp3

$ lpq -Pmp3

mp3 is ready and printing

Rank Owner Job Files Total Size

active andrushock 2 /home/ftp/temp/hope.mp3 9690608 bytes

1st andrushock 3 Bitter_Piece.mp3 6540519 bytes

2nd shocker 46 12-Point.mp3 6063419 bytes

Если вызвать программу lpq с аргументом `-l', то можно увидеть, с каких узлов добавлены музыкальные задания:

$ lpq -Pmp3 -l

mp3 is ready and printing

andrushock: active [job 003midian.home.net]

Bitter_Piece.mp3 6540519 bytes

shocker: 1st [job 046andrushock.home.net]

12-Point.mp3 6063419 bytes

Удаляются файлы из очереди удаленного принтера так же, как и с локального:

$ lprm -Pmp3

andrushock.home.net: dfA007midian.home.net dequeued

andrushock.home.net: cfA007midian.home.net dequeued

Недостатки конструкции

В мире нет ничего идеального, не исключение и эта музыкальная шкатулка. Во-первых, lpd, вместо того чтобы подсчитывать размер задания в очереди печати, выдает размер, занимаемый файлом в системе. Во-вторых, принимая задание вида lpr -Pmp3 /path/to/music/* , демон печати распознает глоббинг и поместит в очередь все файлы из указанного каталога, однако lpq покажет только первую композицию, присвоив ей суммарный размер всех файлов. И, наконец, по умолчанию lpd крайне немногословен, поэтому если возникнет проблема, то решить ее будет непросто (workaround: и на клиенте, и на сервере запускать демон в отладочном режиме: lpd -l).

Радужные перспективы

Несмотря на перечисленные недостатки, которые скорее можно отнести к рудиментам системы печати BSD, вышеописанная система предельно просто расширяема - всего лишь модифицировав входной фильтр, эту шкатулку можно заставить проигрывать любые аудио и даже видеофайлы. Так что если будут идеи - мыль, обсудим.



Malder © 2004
Используются технологии uCoz