ATI Catalyst 8.8, btanks 0.8

К сожалению, новый fglrx все то же унылое ... решето, каким и был до этого

Апофеоз, это, конечно:

XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
after 7448 requests (7447 known processed) with 0 events remain

при завершении fgl_glxgears

В предверии Unreal 2007 for Linux я присматриваю себе новую видеокарту - и ей станет, похоже, станет что-нибудь из линейки GeForce - исключительно из-за fglrx'а

---------------------------------------------------------------------

Кстати, на днях вышел btanks 0.8 - красивая игрушка для офиса/посиделок с друзьями. Собственно, авторам спасибо за "scons install", а то установка btanks до этого требовала отдельного бубна

MPD (Music Player Daemon)

Введение

Для тех, кто в танке: mpd (Music Player Daemon) - это музыкальный плеер с клиент-серверной архитектурой. Вы запускаете сервер (собственно, mpd), указывая, где расположена ваша музыкальная коллекция, после чего подключаетесь к mpd клиентской программой, с помощью которой получаете возможность управлять сервером. Музыку воспроизводить сам mpd => нет необходимости держать запущенным определенный клиент.

Такая организация работы дает несколько больших плюсов:

  • Воспроизведение вынуждено прерывается только после останова сервера (логины/логауты, запуски/остановы XWindow никоим образом на проигрывание музыки не влияют)

  • Плеер доступен и с других компьютеров, объединенных в сеть с тем, на котором mpd выполняется

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


Возможности mpd:

  • Поддержка форматов Ogg Vorbis, FLAC, OggFLAC, MP2, MP3, MP4/AAC, MOD, Musepack и WAV

  • Удалённое управление MPD через сеть (+поддержка IPv6)

  • Потоковое HTTP воспроизведение FLAC, OggFLAC, MP3 и Ogg Vorbis

  • Читает и кэширует информацию метаданных (теги) — (ID3 (id3v1 и id3v2)), комментарии Vorbis и теги MP4

  • MPD умеет перекодировать теги

  • Поддержка буфера при проигрывании (предотвращает пропуски при высокой загруженности или большом времени отклика сети)

  • Поддержка плавного наложения/плавного перехода (Crossfading)

  • Поддержка прокрутки

  • Сохранение, загрузка и управление плейлистами (в формате m3u)

  • Контроль громкости (OSS, ALSA и програмные микшеры)

  • Поддержка широкого диапазона аудио устройств (OSS, ALSA, Sun, esd, ARts, PulseAudio и др.)

  • Демон тестирован на GNU/Linux, FreeBSD, OpenBSD, NetBSD, Solaris и HP-UX


Сервер

Как ни странно, серверная часть mpd называется "mpd". Здесь вы можете забрать пакеты с исходными кодами/бинарными сборками mpd. Текущая стабильная версия mpd - 0.13.2, датируется июнем сего года. Сделать snapshoot с проекта можно с помощью cvs:

svn co https://svn.musicpd.org/mpd/trunk mpd

Я использую Slackware и поэтому компилирую mpd из исходников. К слову, компиляция и установка осуществляется банальным

./configure --prefix=/usr
make
su -c 'make install'

Кстати, в Slackware 12.1 доустановите faad2 - это библиотека, используемая mpd для воспроизведения mp4/aac. Взять faad2 можно на официальном сайте проекта. Компилировать так:

./bootstrap
./configure --with-mp4v2 --prefix=/usr
make
su -c 'make install'

Перед запуском сервера необходимо отредактировать конфигурационный файл. Сделайте:

cp MPD_SRC_DIR/doc/mpdconf.example ~/.mpdconf
mkdir ~/.mpd
mkdir ~/.mpd/playlists

(Здесь MPD_SRC_DIR - папка с исходниками mpd)
Таким образом, главным конфигурационным файлом будет "~/.mpdconf", каталог "~/.mpd" будет главным каталогом программы (в нем будут располагаться логи, коллекционная база данных, файл с данными о текущем статусе плеера) , а в "~/.mpd/playlists" будут лежать созданные вами плейлисты.

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

Отредактируем "~/.mpdconf". Умолчательные настройки хороши, однако кое-что все же нужно "допилить":

  • В секции "REQUIRED PATHS" вместо "~" впишите полные пути к домашнему каталогу пользователя (необходимо, если вы будете запускать mpd root'ом - я делаю именно так, т.к. mpd стартует у меня при загрузке системы из специального демона)

  • Повторите предыдущий пункт для секции "OPTIONAL PATHS" (и обязательно снимите комментарий с "pid_file" и "state_file"

  • Снимите комментарий с полей "bind_to_address" и "port" (порт, на котором будет висеть mpd). Кстати, поскольку у меня запущено несколько mpd, в поле "port" содержаться разные значения для каждого сервера

  • Раскомментируйте поле "password" и отредактируйте его следующим образом: ПАРОЛЬ@read,add,control,admin - таким образом, при подключении к mpd клиентом с паролем "ПАРОЛЬ" вы получите права на чтение потока и всяческое управление им (добавление/удаление треков, останов/запуск и т.п.)

  • Раскомментируйте поле "default_permissions" и установите его в "read" - таким образом, клиенты, подключившиеся к серверу без пароля, смогут только читать поток

  • Поля "filesystem_charset" и "id3v1_encoding" я рекомендую установить в вашу общесистемную кодировку (у меня - "UTF-8"). С "filesystem_charset" все ясно, а вот с "id3v1_encoding" возникает соблазн поставить "CP1251" и получить удобочитаемые русские теги - однако, в этом случае при создании базы треков mpd постоянно вылетает и я счел меньшим злом перекодировать все треки из "CP1251" в "UTF-8" с помощью EasyTag, чем решать проблему копанием в mpd

  • Удобства ради раскомментируйте поле "save_absolute_paths_in_playlists" и установите его в "yes"


Теперь создадим базу треков в коллекции:

mpd --create-db

ИЛИ

mpd --create-db /home/USER/.mpdconf

* Этими же командами вы можете базу данных обновить
** Здесь и далее "USER" - имя текущего пользователя

Запуск:

mpd

ИЛИ

mpd /home/USER/.mpdconf

Останов:

mpd --kill

ИЛИ

mpd --kill /home/USER/.mpdconf

Как вы могли заметить, уникальность каждого запущенного сервера mpd в его конфигурационным файле

Напоследок, демон "rc.mpd" для Slackware:

#!/bin/sh
#
# Start/stop/restart the MPD server.
#

mpd_start() {
echo "Start mpd"
/usr/bin/mpd /home/USER/.mpdconf
/usr/bin/scmpc -f /usr/share/scmpc/scmpc.conf
}

mpd_stop() {
echo "Stop mpd"
/usr/bin/mpd --kill /home/USER/.mpdconf
killall scmpc
}

mpd_restart() {
mpd_stop
sleep 2
mpd_start
}

case "$1" in
'start')
mpd_start
;;
'stop')
mpd_stop
;;
'restart')
mpd_restart
;;
*)
mpd_start
esac

* scmpc - клиент для mpd, отсылающий информации на last.fm о текущем треке. О нем я расскажу немного позже

Консольные клиенты

Собственно, наиболее популярны два консольных клиента - mpc и ncmpc.

mpc

mpc - неитерактивный консольный клиент для mpd. Скачать его (в виде пакета с исходным кодом) можно с официального сайта mpd - вот отсюда (текущая версия 0.12.1)

Установка:

./configure --with-default-host="[PASSWORD@]HOST" --with-default-port="PORT" --prefix=/usr
make
su -c 'make install'

Здесь --with-default-host и --with-default-port указывают, к какому серверу mpd mpc должен подключаться по умолчанию. [PASSWORD@] можно опустить. Если опустить эти два аргумента, то умолчательным сервером будет localhost:6600 (без пароля)

Использование:

mpc COMMAND ARG
mpc --help

Здесь COMMAND - команда серверу, а ARG - аргументы команды. Полный список команд можно получить при вызове mpc с ключом "--help"

Переменные среды MPD_HOST и MPD_PORT определяют, к какому серверу необходимо подключаться. Формат их значений идентичен формату значений ключей --with-default-host и --with-default-port скрипта configure

* Кстати, в MPC_SRC_DIR/doc лежит файл mpc-bashrc - добавьте содержимое этого файла в ~/.bashrc и вы получите удобное дополнение по TAB для mpс

ncmpc

ncmpc - в отличие от mpc, интерактивный клиент для mpd. Официальный сайт проекта - текущая версия: 0.11.1

Как обычно, я устанавливаю ncmpc из исходных кодов:

./configure --with-default-host="[PASSWORD@]HOST" --with-default-port="PORT" --prefix=/usr
make
su -c 'make install'

Запускаем ncmpc:

ncmpc

* Переменные среды MPD_HOST и MPD_PORT определяют, к какому серверу необходимо подключаться. Формат их значений идентичен формату значений ключей --with-default-host и --with-default-port скрипта configure

Управляется ncmpc в основном с клавиатуры, однако доступна и мышь. Функциональные клавиши:

  • F1 - помощью (список сочетаний клавиш)

  • F2 - плейлист

  • F3 - просмотр коллекции

  • F5 - поиск трека по тегамv


Графические клиенты

GUI'вых клиентов великое множество, однако ж мне понравились только два: sonata и qmpdclient

Sonata

Sonata - графический клиент для mpd, написанный на python с помощью gtk2. Sonata многое чего умеет (правда не осиливает очередь воспрозведения) - включая скроблинг и управление из консоли, но я предпочел ей qmpdclient

Официальный сайт Sonata - текущая версия: 1.5.2

QMPDClient

QMPDClient - графический клиент для mpd, написанный на C++ с помощью QT4. Красив и удобен, сворачивается в трей и выводит сообщения о проигрываемой композиции, управляется с помощью мультимедийной клавиатуры. Общаться с last.fm не умеет, однако это поправимо с помощью клиента под названием scmpc

Скачать QMPDClient можно отсюда - текущая версия: 1.0.9

Я устанавливаю клиент из исходных кодов:

tar xzf qmpdclient-1.0.9.tar.gz
cd qmpdclient-1.0.9
wget -c http://havtknut.tihlde.org/qmpdclient/files/translations/ru_RU.ts
qmake-qt4
make
su -c 'make install'

* ru_RU.ts - исходный код локализации

Запустить QMPDClient можно следующим образом:

qmpdclient &

Другие клиенты

Собственно, очень хотелось бы сделать еще пару вещей с mpd:

  1. Отправлять данные о проигрываемом треке на last.fm

  2. Управлять mpd с помощью web-интерфейса

  3. Слушать mpd'овский поток из Windows


Last.fm

Есть две альтернативы:

  1. Sonata - в минусе у Sonat'ы ее графический интерфейс - связь с last.fm прервется с остановом X'ов

  2. Использовать консольный неинтерактивный клиент, заточенный под скроблинг: список таковых можно найти здесь


Я пошел по второму пути и выбрал клиент под названием scmpc

Официальный сайт scmpc - текущая версия: 0.2.2 датирована декабрем 2006-го, однако работает "на ура"

Зависимости, которые нужно удовлетворить в Slackware 12.1:

Компиляция и установка scmpc:

./configure --with-default-host="[PASSWORD@]HOST" --with-default-port="PORT" --prefix=/usr
make
su -c 'make install'

Настройка scmpc (я использую last.fm только одним пользователем):

su -c 'cp SCMPC_SRC_DIR/examples/scmpc.conf /usr/share/scmpc/scmpc.conf'
su -c 'mkdir /var/lib/scmpc'

Здесь SCMPC_SRC_DIR - путь к каталогу с исходным кодом scmpc

Кое-какие замечания относительно /usr/share/scmpc/scmpc.conf:

  • Расскоментируйте поля log_level, log_file, pid_file, cache_file

  • Расскоментируйте поля host, port, timeout - первые два указывают, с каким сервером mpd scmpc работает

  • В поля username и password впишите ваш логин и пароль для last.fm


Запуск scmpc:

/usr/bin/scmpc -f /usr/share/scmpc/scmpc.conf

Останов:

killall scmpc

Примечание:

Q: Все хвалят mpdscribble, почему ты его не используешь?
A: mpdscribble тянет за собой libsoup, а та в свою очередь gnome-common. В-общем, устанавливать Gnome ради клиента для mpd мне лениво

Web-клиенты

Посмотрите полный список web-клиентов вот здесь

Windows-клиент

Проблема взаимоотношений Windows и mpd подробно описана здесь

В Windows я использую QMPDClient. Скачать версию 1.0.9 для Windows можно по этой ссылке

Почитать

Fuse и Python

1. Вводная

Fuse - это проект, предоставляющий программисту функционал для написания драйвера для произвольной файловой системы. Fuse (в Linux) включает в себя модуль ядра, используемый различными программами для связи с драйвером ФС (который является, по существу, исполняемым файлом).

Стратегия разработки драйвера проста - необходимо реализовать некоторый набор функций с определенными прототипами, указатели на которых передать модулю ядра (с помощью вызова некоторой функции - т.н. fuse_main) - после чего при обращении к ФС будут вызываться именно те функции из драйвера, указатели на которые были переданы в fuse_main. Нетрудно догадаться, что диапазон применения fuse очень и очень широк - с ее помощью можно разработать самые "неожиданные" ФС :-)

Плюсы fuse:
  • Код драйвера ФС выполняется в user-space - сразу исчезают многие проблемы, возникающие при отладке модуля ядра

  • У fuse есть много "привязок" к разным ЯП (кроме C, это еще и Python, например)

  • Простые принципы разработки драйверов (простое API)

  • Стабильность, надежность и защищенность



Подробности разработки драйверов ФС на C/C++ для fuse можно узнать в статье: "Разработка собственной файловой системы с помощью FUSE" (ibm.com Россия).

Однако в этой статье я расскажу, как написать драйвер, используя python.

2. Установка "привязок" к fuse для python

Все просто. Для начала получим исходный код "привязок":

Проследуйте на страницу FUSEWiki - FusePython и выберите понравившийся вам способ загрузки.

Я использовал Mercurial:

hg clone http://mercurial.creo.hu/repos/fuse-python-hg

После загрузки перейдите в каталог с исходниками fuse-python и сделайте:

python setup.py build
su -c 'python setup.py install'


Вы получите модуль fuse, в котором содержаться вся необходимые классы.

3. Небольшой пример

Давайте напишем драйвер для "игрушечной" виртуальной ФС.

В начале - каркас драйвера:
  1. Первым делом мы импортируем нужные модули:

    import os,stat
    import fuse

  2. Теперь необходимо сообщить fuse-python какую ее версию мы используем:

    fuse.fuse_python_api = (0, 2)

  3. Описываем базовый для нашего драйвера класс (он будет наследовать класс fuse.Fuse):

    class simpleFS(fuse.Fuse):
      #функции
      #TODO

  4. Описываем функцию, которая будет "запускать" наш драйвер:

    def runSimpleFS():
      usage='Simple FS ' + fuse.Fuse.fusage
      fs = simpleFS(version="%prog " + fuse.__version__,usage=usage,dash_s_do='setsingle')
      fs.parse(errex=1)
      fs.main()


    Как вы могли заметить, принципиально важными являются вызов конструктора fuse.Fuse (с правильным списком аргументов), вызов fs.parse() и вызов fs.main(). fs.main() это и есть как раз та самая fuse_main. Указатели на функцию в fuse-python подменяются функциями-членами_класса fuse.Fuse.

    Важное замечание: после вызова fs.main() драйверу перестает быть доступной консоль, из которой, собственно, драйвер и был запущен. В частности, теряется связь с STDIN, STDOUT, STDERR - т.е. мы сможем догадаться об исключенях только по результатам работы драйвера.

  5. Вызываем runSimpleFS():

    runSimpleFS()


Каркас готов.

Теперь давайте определимся с тем, что будет представлять из себя наша ФС:
  1. 2 каталога - '/' и '/simple' - оба с правами 0555 и root.root в качестве пользователя.группы_пользователя

  2. 1 файл - '/README' (0444 root.root)


Реализация нашего класса:

  1. Конструктор. В нем принципиально важно вызвать конструктор базового класса со всеми переданными в конструктор simpleFS аргументами (а self.README - содержимое файла '/README'):

    def __init__(self, *args, **kw):
      fuse.Fuse.__init__(self, *args, **kw)
      self.README = 'This is simple FS\n'

  2. Пользовательские действия с ФС (системные вызовы и прочее). На каждой такой функции в fuse.Fuse стоит "заглушка". Нам остается только переопределить нужные нам функции:


    # getattr вызывается при получении информации об объекте ФС. Например, при использовании команды ls

    def getattr(self, path):
      # В объекте fuse.Stat() вернем интересующую информацию
      st = fuse.Stat()
      # "Режим" - права доступа, тип объекта
      st.st_mode = 0
      # Номер inode
      st.st_ino = 0
      st.st_dev = 0
      # Количество ссылок на объект
      st.st_nlink = 0
      # ID владельца объекта
      st.st_uid = 0
      # ID группы владельца объекта
      st.st_gid = 0
      # Размер объекта
      st.st_size = 0
      # Временные штампы
      st.st_atime = 0
      st.st_mtime = 0
      st.st_ctime = 0
      if path == '/' or path == '/simple':
        # Каталоги
        st.st_mode = stat.S_IFDIR | 0755
        st.st_nlink = 3
      elif path == '/README':
        # Файлы
        st.st_mode = stat.S_IFREG | 0444
        st.st_nlink = 1
        st.st_size = len(self.README)
      else:
        # path не существует
        return -errno.ENOENT
      return st

    # readdir вызывается при попытке просмотра содержимого каталога. Например, при использовании ls

    def readdir(self, path, offset):
      # В каждом каталоге есть '.' и '..'
      yield fuse.Direntry('.')
      yield fuse.Direntry('..')
      if path == '/':
        # Кроме того, в '/' есть еще и 'README' и 'simple'
        yield fuse.Direntry('README')
        yield fuse.Direntry('simple')

    # open вызывается при попытки открыть файл. Мы должны проверить флаги доступа - наш единственный файл '/README' доступен только на чтение

    def open(self, path, flags):
      if path != '/README':
        return -errno.ENOENT
      accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
      if (flags & accmode) != os.O_RDONLY:
        # Ошибка доступа
        return -errno.EACCES

    # read вызывается при попытки прочитать данные из файла
    # offset - смещение в читаемом файле
    # size - размер считываемого ("запрощенного") блока
    # read возвращает считанные символы

    def read(self, path, size, offset):
      if path != '/README':
        return -errno.ENOENT
      slen = len(self.README)
      if offset < slen:
        if offset + size > slen:
          size = slen - offset
        buf = self.README[offset:offset+size]
      else:
        buf = ''
      return buf

    # statfs вызывается в ответ на запрос информации о ФС

    def statfs(self):
      # Вернем информацию в объекте класса fuse.StatVfs
      st = fuse.StatVfs()
      # Размер блока
      st.f_bsize = 1024
      st.f_frsize = 1024
      st.f_bfree = 0
      st.f_bavail = 0
      # Количество файлов
      st.f_files = 2
      # Количество блоков
      # Если f_blocks == 0, то 'df' не включит ФС в свой список - понадобится сделать 'df -a'
      st.f_blocks = 4
      st.f_ffree = 0
      st.f_favail = 0
      st.f_namelen = 255
      return st


Вот и все. Драйвер готов (исходный код драйвера лежит здесь).

Проверка:

mkdir smpfs
python simplefs.py smpfs
ls -la smpfs/
ls -la smpfs/simple
cat smpfs/README
df
su -c 'umount smpfs'


Заметьте, что первым параметром в скрипт передается точка монтирования (каталог 'smpfs' в нашем случае).

В случае, если этого примера вам показалось мало - посмотрите в каталог 'example' дистрибутива fuse-python. Там есть кое-что интересное.

4. Почитать



5. BashOrgFS

Здесь лежит моя поделка на заданную тему. bash.org.ru представлен в виде файловой системы.

Монтировать так:

./bashorg ТОЧКА_МОНТИРОВАНИЯ.

Заранее - это просто пример. Используйте на свой страх и риск. Предварительно читайте README ;-)

6. За сим все. Успехов!

arora

(по мотивам LOR'а)

Проскальзывала на днях новость об очередном "броузере на qt/webkit". Называется сие поделие - "arora". В-целом - неплохо. Мне понравилось.

Сайт программы. Вам понадобится QT > 4.3 (у меня - 4.4).

Итак, у aror'ы есть:
  • История

  • Закладки (храняться в XBEL-формате (это хорошо, ибо konqueror хранит свои в нем же - процесс импорта сводится к паре кликов))

  • Табы

  • Оригинальный "бар" загрузки страницы (фон строки ввода адреса)

  • javascript

  • Широкий спектр настроек

  • plug-in'ы (flash обещают в версиях собранных с QT 4.5)


Стоит заметить, что arora некорректно обрабатывает некоторые сайты (например, ВКонтакте), кушает приличный кусок памяти (правда, меньший чем opera 9.50 при большем количестве открытых вкладок), падает (редко, но падает же) и нет никакого внутреннего или поддержки внешнего хранилища данных/паролей (особенно досадно, конечно).

Скриншоты:


(flash'а еще нет, зато есть оригинальный бар загрузки страницы)

KDE4

Наконец-то дошли руки до KDE4.

Версия: в итоге ею стал срез svn от 4-го августа.

Компилировал: как release (вместо debugfull по умолчанию). Система - моя любимая Slackware 12.1.

Проблемы при компиляции: clucene вывел меня из себя, однако ларчик открывался просто - нужно было всего лишь обновить cmake до версии 2.6 (в Slackware 12.1 по умолчанию - 2.4).

Проблемы при использовании:
  • kget красив и функционален, но "вываливается" после завершения каждой закачки

  • amarok 2 и k3b (они, конечно, не часть KDE4, но все же) совершенно не юзабельны

  • Скорость работы оставляет желать лучшего


Мораль: жду KDE 4.2. Учитывая, какими темпами KDE 4 взрослеет (я последний раз пробовал кеды в апреле сего года), я думаю, KDE 4.2 будет "самое оно".