14 июня 2010 г.

И снова о разрезании lossless-аудио (ape, flac, wv, wav) по файлу cue

Ранее я выкладывал перевод одной заметки о том, как разрезать lossless-аудио на отдельные треки. Однако, в комментариях мне подсказали более простой способ.


Для этого понадибится утилита shntool (в Debian и Ubuntu живёт в одноимённом пакете). Вообще, это настоящий швейцарский армейский нож в области работы со звуковыми файлами (в том числе и сжатыми), в чём можно убедиться, открыв соответствующий man:
man shntool
Вот перечень некоторых команд, которые эта утилита поддерживает:
  • len — отображает продолжительность, размер и свойства звуковых данных
  • join — объединяет несколько файлов в один
  • split — разбивает звуковой файл на несколько отдельных файлов
  • cue — генерирует файл CUE или список точек разбиения по набору файлов
  • conv — преобразует из одного формата в другой
  • trim — удаляет тишину по краям записи
Список поддерживаемых форматов тоже немал: wav (RIFF WAVE), aiff (Audio Interchange File Format), shn (Shorten low complexity waveform coder), flac (Free Lossless Audio Codec), ape (Monkey's Audio Compressor), ofr (OptimFROG Lossless WAVE), lpac (Lossless Predictive Audio Compression), wv (WavPack Hybrid Lossless Audio Compression), alac (Apple Lossless Audio Codec) и другие, менее распространённые.

Естественно, для поддержки форматов нужно доустанавливать соответствующие утилиты. Для flac, ape и wv:
sudo apt-get install flac wavpack monkeys-audio
Собственно команда для разрезания будет иметь вид:
Эта команда не только разобьёт исходный flac-файл, но и переименует каждый трек в соответствии с форматом:

Исполнитель (Альбом) - Номер - Название

Естественно, можно указать и другой формат, задав свою строку и используя постановочные символы %p, %a, %n, %t.

Если файлы Music.flac и Music.cue расположены в одной папке, имеют одинаковое имя, как в данном случае и других подобных файлов нет, то можно использовать следующий скрипт:
#!/bin/bash
f=`ls *.cue`
f=${f%.cue}
shntool split -f "$f.cue" -o flac "$f.flac" -t "%p (%a) - %n - %t"
Я его назвал split_flac и поместил в ~/bin. Чтобы им воспользоваться достаточно зайти в директорию с разрезаемыми файлами и выполнить всего одну команду:
split_flac
Аналогичный скрипт можно написать и для формата APE. А можно сделать один большой интеллектуальный скрипт, если не лень.

Чтобы не было закорючек в именах, нужно следить, чтобы файл cue был в той же кодировке, что и текущая локаль (обычно, UTF-8).

Единственный минус — теги будут пустыми, но их можно заполнить командой cuetag или какой-то специализированной утилитой наподобие EasyTAG.

Читать дальше…

8 июня 2010 г.

Решето Эратосфена / Sieve of Eratosthenes

Programming Praxis, 19.02.2009

Более двух тысяч лет назад Эратосфен, который вычислил окружность Земли, расстояние до Солнца и наклон земной оси, изобрёл широту и долготу, а также придумал високосный день, создал систематический метод перечисления всех простых числе, который используется и по сей день.
Эратосфен родился в Кирене (на территории современной Ливии) и жил с 276 г. до н. э. по 194 до н. э. Он провёл большую часть своей жизни в Александрии (Египет), где был вторым главой Великой библиотеки перед Аполлонием Родосским.

Решето Эратосфена начинается с создания списка натуральных чисел до желаемого предела; проиллюстрируем метод, вычислив простые числа до тридцати:

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

Теперь возьмём первое число в списке — 2 — и вычеркнем каждое второе число:

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

Затем берём следующее невычеркнутое число в списке — 3 — и вычёркиваем каждое третье число; некоторые из них окажутся уже вычеркнутыми:

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

повторяем последний шаг для следующего невычеркнутого числа — 5:


2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

И так далее, каждый раз вычёркивая все числа, кратные следующему невычеркнутому числу в списке. Все невычеркнутые числа к концу процедуры будут простыми:

2 3 5 7 11 13 17 19 23 29

Этот метод называется решетом, потому что он просеивает весь исходный диапазон чисел в поисках простых чисел.

Решето допускает некоторые оптимизации.

Во-первых, нужно рассматривать только нечётные числа, так как первый проход вычеркнет все чётные за исключением 2, которое можно рассматривать отдельно.

Во-вторых, вычёркивание нужно начинать с квадрата числа, которое рассматривается в данный момент, так как все меньшие составные числа уже были вычеркнуты на предыдущих шагах; например, рассматривая 3, вычёркивание нужно начинать с 9, так как 6 было вычеркнуто, когда рассматривали 2.

В третьих, процедура останавливается на квадратном корне из максимального числа, так как все простые числа, большие него уже будут вычеркнуты к этому моменту. Так, в рассмотренном выше примере не было необходимости проверять числа, большие либо равные 7, так как квадрат 7 больше 30 — наибольшего числа в списке.

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


Решение.
Jos Koot написал следующую версию решета Эратосфена:


(define (primes n)
(let* ((max-index (quotient (- n 3) 2))
(v (make-vector (+ 1 max-index) #t)))
(let loop ((i 0) (ps '(2)))
(let ((p (+ i i 3)) (startj (+ (* 2 i i) (* 6 i) 3)))
(cond ((>= (* p p) n)
(let loop ((j i) (ps ps))
(cond ((> j max-index) (reverse ps))
((vector-ref v j)
(loop (+ j 1) (cons (+ j j 3) ps)))
(else (loop (+ j 1) ps)))))
((vector-ref v i)
(let loop ((j startj))
(if (<= j max-index)
(begin (vector-set! v j #f)
(loop (+ j p)))))
(loop (+ 1 i) (cons p ps)))
(else (loop (+ 1 i) ps)))))))


Существует миллион простых числе, меньших, либо равных 15485863:


> (length (primes 15485863))
1000000


Моё решение.

from math import sqrt

def sieve(n):
l = range(3,n+1,2)
i = 0
while 2*i+3 <= sqrt(n):
k = l[i]
l[(k**2-3)/2:(n-1)/2:k] = [0] * ((n-k**2+1)/(2*k)+1)
i += 1
while l[i] == 0:
i += 1
return [2] + filter(lambda x: x != 0, l)

print len(sieve(15485863))

Казалось бы, использование сечений — не самый оптимальный способ присвоить значение сразу многим элементам списка, но при замене страшной строчки «l[(k**2-3)/2:(n-1)/2:k] = [0] * ((n-k**2+1)/(2*k)+1)» на цикл программ стала завершать работу не за 3.172 с, а за 5,056 с.

Всего же для просеивания 15485863 числе программе потребовалось 545 итераций. Из упомянутых трёх секунд только полторы уходило на собственно просеивание. Остальное время программа отфильтровывала вычеркнутые элементы.

Читать дальше…

7 июня 2010 г.

Обратный польский калькулятор / RPN Calculator

Дисклеймер. Хотелось бы поделиться с людьми, которые не особо знают английский, задачками с довольно интересного сайта Programming Praxis. Готовых переводов задач я не нашёл, а потому буду потихоньку сам их тут выкладывать. Задачки простые, но для того, чтобы не терять навыки программирования — самое то.

Programming Praxis, 19.02.2009

Реализовать обратный польский калькулятор, принимающий выражения вида «19 2.14 + 4.5 2 4.3 / - *», которое обычно вычисляется как «(19 + 2.14) * (4.5 - 2 / 4.3)» и соответствует 85.2974. Программа должна читать выражение со стандартного входа и выводить вершину стека с символом конца строки в стандартный вывод. Программа должна сохранять состояние стека операндов между выражениями.


Решение.
Единственная сложность заключается в обработке новой строки, которая в Scheme трактуется как пробел. Функция (op token) преобразует знак, из символа, полученного со входа, в оператор, который может быть использован для вычислений. Формат первой строки программы специфичен для Chez Scheme, но большинство реализаций Scheme предоставляют что-то подобное.


#! /usr/bin/scheme –script
(define (next)
(cond ((eof-object? (peek-char)) (exit))
((char=? (peek-char) #\space) (read-char) (next))
((char=? (peek-char) #\newline) (read-char) ‘nl)
(else (read))))

(define (op token) (case token ((+) +) ((-) -) ((*) *) ((/) /)))

(let rpn ((token (next)) (stack ‘()))
(cond ((eq? ‘nl token) (display (car stack)) (newline) (rpn (next) (cdr stack)))
((number? token) (rpn (next) (cons token stack)))
(else (rpn (next) (cons ((op token) (cadr stack) (car stack)) (cddr stack))))))


Моё решение.

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from sys import stdin, stdout

def calc():
stack = []
result = None
while True:
line = yield result
for token in line.split():
try:
number = float(token)
stack[:0] = [number]
result = number
except ValueError:
try:
result = {
'+': lambda x, y: x + y,
'-': lambda x, y: x - y,
'*': lambda x, y: x * y,
'/': lambda x, y: x / y
}[token](stack[1], stack[0])
stack[0:2] = [result]
except IndexError:
raise ValueError, 'Stack is empty'
except KeyError:
raise ValueError, 'Unknown operation'
c = calc()
c.next()

for line in stdin.xreadlines():
print >> stdout, c.send(line)


Тут есть несколько необычных для новичка моментов.

line = yield result
— это «вывернутый наизнанку» вызов функции, который позволяет разбить цикл обработки на две части: работу со стеком и получение строк со стандартного ввода. Команда yield возвращает значение подобно return, но функция при этом не завершается и будет продолжена при вызове метода send снаружи. причём, аргумент send будет передан через yield внутрь функции. Звучит запутанно, но генераторы — это действительно очень мощная и гибкая штука.

Другая необычность — использование индексирования словаря. Это позволяет ввести конструкцию, аналогичную, например, switch в C, без использования if—elif. Так код выглядит чище, хотя, конечно, тратятся ресурсы на создание анонимного словаря и поиск ключа в нём.

Странные индексы списка stack с двоеточиями — это сечения (slices). Тоже довольно удобная штука. Они есть также в MatLab и Fortran, где без них программирование заметно усложнилось бы.

Читать дальше…

5 ноября 2009 г.

Как сделать deb-пакет со своими скриптами

Рано или поздно у продвинутого пользователя линукса накапливается набор собственных скриптов, хранящихся где-то в «~/bin». Но каталог с программами не так красиво смотрится в домашнем каталоге, да и потом если делиться с друзьями, то приходится отправлять в архиве, говорить куда что копировать, убеждать их, что загромождение домашнего каталога — неизбежное зло. Можно, конечно и куда-то в «/usr/local/bin» их поместить, но можно потратить десять минут и собрать пакет, который потом легко устанавливается (и удаляется) штатными средствами. Причём туда, куда надо.

Посмотрим, как это делается.

В качестве примера скриптов возьмем, например следующие два.

Первый загружает цитаты с lorquotes.ru.
#!/bin/sh
[ -x ~/.lor ] || mkdir ~/.lor
wget http://lorquotes.ru/fortraw.php -O -| iconv -f koi8-r -o ~/.lor/lor
strfile ~/.lor/lor ~/.lor/lor.dat
А второй — выводит и при помощи утилиты fortune.
#!/bin/sh
fortune ~/.lor
Назовем их соответственно «lor-update» и «lor».

Сохраним их в отдельный каталог, который при сборке пакета должен иметь имя вида «пакет-версия». В нашем случае это будет «lorquotes-0.1».

Теперь создадим заготовку пакета при помощи команды dh_make (есть в репозитории под именем — сюрприз! — «dh-make»). Для этого в нашем каталоге выполним следующую команду:
dh_make --createorig -c gpl3 -e user@example.com -i -p lorquotes_0.1
Довольно длинно, не так ли? Разберём по порядку:
--createorig — создать отдельную папку с исходниками, это будет нужно при создании пакета;
-c gpl3 — указать в качестве лицензии GPL3 (какие ещё есть лицензии ,можно посмотреть в man-страничке утилиты dh_make);
-e user@example.com — электронная почта собравшего пакет (то есть ваш);
-i — говорим, что пакет не зависит от платформы (bash-скрипты везде одинаковы ведь);
-p lorquotes_0.1 — указываем имя пакета (вообще, необязательно).

Утилита спросит, всё ли она правильно поняла, на что мы честно соглашаемся и заходим в папку.

Как видим, старое содержимое скопировалось в каталог «lorquotes-0.1.orig» (спасибо опции --createorig), а в «lorquotes-0.1» появился каталог «debian» с кучей файликов непонятного назначения. Собственно, содержимое этого каталога и определяет как будет вести себя пакет при установке и что он будет содержать.

Но сперва нужно создать мейкфайл. Это специальный файл, имеющий имя Makefile и говорящий сборщику пакета, как скомпилировать исходнуе тексты и куда устанавливать его содержимое. Структура нашего мейкфайла очень проста:
DESTDIR =
BIN = $(DESTDIR)/usr/bin

build:
true

install:
install -d $(BIN)
install -m755 lor $(BIN)
install -m755 lor-update $(BIN)
Заметьте, что некоторые строки набраны с отступом при помощи табуляции. Именно так и нужно набирать. Это важно!

Мейкфайл — это просто предписание команде «make» выполнить определенный набор действий.

В строке 1 определены специальные переменные: DESTDIR — каталог, в который будет устанавливаться наш пакет. Эта переменная обязательно должна быть в мейкфайле, так как черех неё потом сборщик пакета указывает каталог назначения.

В строке 2 указан каталог, куда будут установлены наши скрипты. Без этой переменной уже можно было обойтись, так как она пользовательская и введена для удобства.

Строка с «build» — это одна из целей, которых должен достичь make. После двоеточия можно было указать список целей, от которых цель «build» зависит, но у нас и компилировать-то нечего, потому ничего и не указано. После цели идут команды (внимание, с отступом!), которые необходимо выполнить для достижения этой цели. Так как ничего выполнять не надо, то там стоит команда true, которая ничего не делает (такая у неё работа).

Аналогично описана цель «install». Но тут уже нужны действия: а именно создание каталога назначения и копирование в него с соответствующими правами наших скриптов. Вместо обычных команд создания и копирования используется утилита install, которая более интеллектуальна и специально для этих целей предназначена.

Итак, создаем в папке со скриптами (не в debian) мейкфайл под именем Makefile. Теперь мы можем при помощи команд «make» (ничего не делает, т.к выполнится первая цель в файле, т.е. «build») и «sudo make install» (копирует скрипты куда надо) собрать и установить вручную наши скрипты. Но вручную нам не нужно, мы ведь пакет хотим собрать. Поэтому переходим к следующему этапу.

Настроим свойства нашего пакета. Перейдём в каталог «debian» и откроем файл «control». Он содержит информацию о пакете, его зависимостях и так далее. Заполним его как анкету.

Source — название того, что мы сейчас собираем,
Section — в какую секцию дерева репозитория поместить наш пакет,
Priority — важность пакета,
Maintainer — сборщик,
Build-Depends — какие программы нужны для сборки пакета,
Standards-Version — версия стандарта, описывающего сборку пакетов,
Homepage — домашняя страничка (если есть),
Package — имя собственно deb-пакета,
Architecture — архитектура, под которую он собирается (i386, amd64 и иже с ними),
Depends — от каких пакетом наш зависит,
Description — описание, короткое в той же строке и длинное ниже (обратите внимание на пробел в начале строки с длинным описанием).

Я для примера сделал такой файл:
Source: lorquotes
Section: misc
Priority: optional
Maintainer: Vasiliy Pupkin
Build-Depends: debhelper (>= 7)
Standards-Version: 3.8.3
Homepage: http://pupkin.example.com/lorquotes/

Package: lorquotes
Architecture: all
Depends: wget,fortunes
Description: Small LOR quotes utility
Shows you random quote from lorquotes.ru.
Думаю, указывать в зависимостях шелл и libc6 смысла нет. Они точно есть в любой системе (или нет?).

Теперь подправим файл «changelog». Он содержит историю версия нашего пакета. Во время правки не забывайте, что он тоже имеет строгий формат и не добавляйте лишние отступы и строки.

Вот мой вариант:
lorquotes (0.1-1) unstable; urgency=low

* Initial release

-- Vasiliy Pupkin Thu, 05 Nov 2009 19:53:58 +0200
unstable — это имя ветки дистрибутива, для которой готовится пакет, а urgency — это приоритет.

В том же каталоге есть файл «rules». Это обычный мекфайл, который и отвечает за конфигурирование и сборку пакета. Но так как мы ничего экстраординарного не делали, оставим всё как есть.

В файле «copyright» находится лицензия. Мы лицензию сразу указали, так что и этот файл трогать не будем.

Итак, остались ещё следующие важные для нас файлы.

«cron.d.ex». Переименовываем его в «cron.d». Он содержит информацию о регулярных действиях, которые будет выполнять установленная программа. В нашем случае — ежедневное обновление базы цитат в полдень:
#
# Regular cron jobs for the lorquotes package
#
0 12 * * * root [ -x /usr/bin/lor-update ] && /usr/bin/lor-update


«postrm.ez». Переименовываем в «postrm». Это скрипт, запускаемый после удаления пакета. Заставим его очищать нашу базу цитат, хранящуюся в «~/.lor». Хотя хранить базу в домашнем каталоге не совсем верно идеологически. Но, думаю, после этого поста читатель и сам исправит эту неточность. Итак, мой «postrm»:
#!/bin/sh
# postrm script for lorquotes
#
# see: dh_installdeb(1)

set -e

case "$1" in
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
rm -rf ~/.lor
;;

*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac

# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.

#DEBHELPER#

exit 0
Остальные файлы нам не нужны и смело их удаляем. Это разные заготовки. Например, для man-страниц.

Переходим теперь в каталог со скриптами (т.е. на уровень выше) и даём команду на сбору пакета:
debuild
Она собирает пакет, проверяет на ошибки, а потом пробует его подписать вашим GPG-ключом. Но даже если ей подписать не удастся, пакет будет собран. Найти его можно будет в каталоге уровнем выше. Там же будет архив с исходниками и вспомогательные файлы, нужные, если вы хотите создать свой репозиторий или загрузить пакет в уже существующий.

Конечно, при сборке пакета будут предупреждения. Но мы ведь не закачивать его в дебиановский репозиторий будем, а для себя собираем. Так что устранение причин предупреждений остаётся в качестве домашнего задания читателю. (Кстати, это несложно.)

Вот и всё! Осталось только установить пакет. :)

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

А вот архив с исходниками и пакетом.

Читать дальше…

2 ноября 2009 г.

Отправка email из командной строки

О том как отправлять сообщения через jabber, я уже написал. А вот сегодня мне захотелось написать утилитку, которая бы делала то же самое и с теми же (примерно) параметрами командной строки, но для электронной почты. Конечно, в линуксе полно консольных почтовых программ (я в курсе, что есть команда mail), но мне не нужны все их возможности, а кроме того, хотелось бы ещё и кроссплатформенности (я в курсе, что в Windows есть утилита blat) и возможности быстро самому что-то дописать. Вот, что получилось.

Не буду тянуть, сразу приведу код скрипта.
#!/usr/bin/env python
import smtplib, ConfigParser, email.mime.text, getopt, os, sys, locale

name = os.path.basename(sys.argv[0])

optlist, args = getopt.getopt(sys.argv[1:], 's:f:')
if len(args) < 2:
print "Send a message via email"
print
print "Syntax:", name, "[-f from] [-s subject] email text"
print "email\trecipient's e-mail address"
print "from\tsender's email"
print "subject\tmessage subject"
print "text\tmessage, use '-' for stdin"
sys.exit(0)

configFile = os.path.join(os.environ['HOME'], '.' + name)
config = ConfigParser.RawConfigParser()
try:
config.read(configFile)
fromEmail = config.get('From', 'E-mail')
smtpServer = config.get('SMTP', 'Server')
smtpLogin = config.get('SMTP', 'Login')
smtpPassword = config.get('SMTP', 'Password')
except:
print "Default configuration was written to", configFile
config.add_section('From')
config.set('From', 'E-mail', 'user@example.com')
config.add_section('SMTP')
config.set('SMTP', 'Server', 'smtp.example.com')
config.set('SMTP', 'Login', 'user')
config.set('SMTP', 'Password', '********')
f = file(configFile, 'w')
config.write(f)
f.close()
sys.exit(0)

toEmail = args[0]
subject = ''
for option, value in optlist:
if option == '-s':
subject = value
elif option == '-f':
fromEmail = value

encoding = locale.getpreferredencoding()
if args[1] == '-':
message = email.mime.text.MIMEText(sys.stdin.read(), 'plain', encoding)
else:
message = email.mime.text.MIMEText(' '.join(args[1:]), 'plain', encoding)

message['Subject'] = subject
message['From'] = fromEmail
message['To'] = toEmail

server = smtplib.SMTP(smtpServer)
server.login(smtpLogin, smtpPassword)
server.sendmail(message['From'], message['To'], message.as_string())
server.quit()
Всё это сохраняем в файл с именем, например, «mailto» и даём права на выполнение:
chmod +x mailto
После первого создаётся файл с настройками подключения. По умолчанию это файл «.mailto» (если скрипт называется «mailto», конечно) в домашнем каталоге. В нём нужно указать адрес отправителя и настройки smtp-сервера.

Параметров у скрипта минимум, только то, что нужно. Есть два опциональных для указания темы сообщения и адреса отправителя (по умолчанию берётся из файла с настройками). Для них используются ключи «-s» и «-f» соответственно (от слов «From» и «Subject»).

Обязательных параметров всего два и они без ключей. Это адрес получателя собственно текст сообщения. Если вместо текста поставить «-», то текст будет браться из стандартного входа, что удобно для отправки результатов вывода какой-то программы.

Использовать программу можно для чего угодно. Например, чтобы отправить список пользователей себе на ящик можно воспользоваться командой:
who | mailto user@example.com -
Я, например, использую этот скрипт, чтобы автоматически в определённое время слать себе СМС с напоминанием о чём-либо через гейт «email—SMS» моего мобильного оператора. Получилось удобно.

Читать дальше…

1 ноября 2009 г.

Отправка jabber-сообщений из командной строки

О том, как отправить jabber-сообщение из консоли при помощи клиента Gajim, я уже писал ранее. Тем не менее, использование gajim-remote имеет ряд недостатков: нужно установить сам Gajim и запустить его. Это может вызвать некоторые затруднения, например, на сервере, где вовсе может не быть графического интерфейса. Однако, проблема имеет и более простое решение.

Сделаем скрипт, которому бы в качестве параметров передавались данные учётной записи jabber, JID отправителя и текст сообщения. В качестве основы возьмём питоновскую библиотеку xmpppy. В частности, рассмотрим повнимательнее один из примеров, входящих в её комплект, который (сюрприз!) как раз и предназначен для отправки сообщений из консоли. Остаётся только его чуть-чуть «допилить» по вкусу.

Итак, нам потребуется библиотека. Они есть в репозиториях Debian (да и других популярных дистрибутивов), поэтому устанавливаем как обычно:
sudo aptitude install python-xmpp python-dnspython
Без python-dnspython работать тоже будет, кстати. Но лучше поставить, так как в этом случае придётся вводить точное имя узла, на котором располагается сервер.

А вот и сам скрипт:
#!/usr/bin/env python
import sys,os,xmpp,time,ConfigParser

name = os.path.basename(sys.argv[0])

if len(sys.argv) < 2:
print "Send a message via Jabber (XMPP)"
print "Syntax:", name, "JID text"
print "JID\trecipient's Jabber ID"
print "text\tmessage, use '-' for stdin"
sys.exit(0)

toJID = sys.argv[1]
if sys.argv[2] == '-':
text = sys.stdin.read()
else:
text = ' '.join(sys.argv[2:])

configFile = os.path.join(os.environ['HOME'], '.' + name)
config = ConfigParser.RawConfigParser()

try:
config.read(configFile)
fromJID = config.get('Connection', 'JID')
password = config.get('Connection', 'Password')
except:
print "Default configuration was written to", configFile
config.add_section('Connection')
config.set('Connection', 'JID', 'user@example.com/home')
config.set('Connection', 'Password', '********')
f = file(configFile, 'w')
config.write(f)
f.close()
sys.exit(0)

fromJID = xmpp.protocol.JID(fromJID)
client = xmpp.Client(fromJID.getDomain(),debug=[])

conn = client.connect()
if not conn:
print 'Could not connect!'
sys.exit(1)
print 'Connected with', conn

auth = client.auth(fromJID.getNode(), password, resource=fromJID.getResource())
if not auth:
print 'Could not authenticate!'
sys.exit(1)
print 'Authenticated using', auth

messageID = client.send(xmpp.protocol.Message(toJID, text))
print 'Message was sent'

time.sleep(1)
client.disconnect()
Скрипт довольно простой, так что разбирать его работу не буду.

Всё это сохраняем в каталог «~/bin» под именем, например, «jsend». Имя и каталог значения не имеют, просто «~/bin» удобен для хранения пользовательских скриптов, так как он входит в переменную PATH и для запуска скритов из него достаточно указать их имена. В любом случае нужно разрешить выполнение нашей программки:
chmod +x jsend
Рассмотрим её работу. После первого запуска утилита создаёт в домашнем каталоге файл с JID и паролем отправителя. Это удобнее, чем вводить пароль в качестве параметра командной строки, так как в этом случае никто не сможет его подсмотреть. Да и доступ к файлу можно будет закрыть. Файл поличит имя, совпадающее с именем скрипта, но с точкой впереди, чтобы не отображаться лишний раз в списке файлов. В моём случае имя будет «~/.jsend». Естественно, файл после первого запуска нужно будет открыть и впесать свои JID и пароль.

Формат запуска скрипта:
jsend JID text
JID — это идентификатор получателя сообщения, а text — это собственно текст, который нужно отправить.

Если текста много или нужно отправить вывод какой-либо команды, то вместо text можно поставить «-». Например, команда
df | jsend user@example.com -
отправит информацию о заполненности разделов на дисках пользователю user@example.com.

Также можно настроить отправку сообщений в определённое время при помощи команды at, что тоже иногда оказывается удобным.

Читать дальше…

27 октября 2009 г.

Разрезаем lossless-аудио (ape, flac, wv, wav) по файлу cue

Понимаю, что теме этого поста наверняка написано огромное количество статей, мануалов и прочих ЧаВо. Но каждый раз искать лень, проще один раз сделать узелок на память в блоге.

(Это перевод англоязычной заметки. См. также описание более простого способа.)

Итак, задача такова: дана пара файлов, предположим sample.cue и sample.flac, с каким-либо альбомом. Требуется получить треки альбома в отдельных flac-файлах.Если у вас linux, то делается это в два счёта. Ниже следует перевод одной довольно неплохой статьи с решением проблемы.


Файлы с lossless-аудио могут быть разрезаны по cue-файлу при помощи утилиты «shnsplit» (входит в пакет «shntool»). Также потребуется утилита «cuebreakpoints» (из пакета «cuetools»). Чтобы установить их, откройте терминал и введите следующее (эти пакеты есть в Ubuntu и Debian):
sudo apt-get install cuetools shntool

Кроме этого потребуются приложения для работы с выбранным форматом. Для Monkey’s Audio нужна будет утилита «mac» (в Debian есть пакет «monkeys-audio»). Для FLAC и WavePack потребуется установить соответственно «flac» и «wavpack»:
sudo apt-get install flac wavpack

Утилите shnsplit требуется для работы список точек, в которых нужно делить звуковой файл. Очень кстати тут оказывается утилита cuebreakpoints, которая печатает список таких точек по cue- или toc-файлу в формате, используемом в shnsplit. Можно создать конвейер между cuebreakpoints и shnsplit следующим образом:
cuebreakpoints sample.cue | shnsplit -o flac sample.flac

В этом примере flac-файл с именем «sample.flac» разрезается по точкам, содержащимся в «sample.cue» и результат выводится в формате FLAC.

Выходной формат задаётся параметром «-o». Если не указать формат, то файлы будут сохрняться в формате по умолчанию, то есть в виде wav-файлов.

Чтобы разрезать файл в формате Monkey’s Audio и сохраниеть результаты в формате FLAC, нужно выполнить следующую команду:
cuebreakpoints sample.cue | shnsplit -o flac sample.ape

По умолчанию для выходных файлов используется префикс «split-track» (то есть по умолчанию файлы будут иметь имена: split-track01, split-track02, split-track03,…). Можно задать собственный префикс при помощи опции «-a».

Чтобы посмотреть список всех параметров наберите «shntool split -h» или «shnsplit -h».

В звуковые файлах, полученных с помощью shnsplit не будут записаны данные об исполнителе, альбоме и так далее. Однако, можно воспользоваться скриптом cuetag (также входящим в пакет cuetools) для того, чтобы перенести данные из cue-файла в отдельные дорожки. Можно указать отдельные файлы, соответствующие дорожкам, содержащимся в cue-файле:
cuetag sample.cue split-track01.flac split-track02.flac split-track03.flac split-track04.flac

Эта команда перенесёт теги, содержащиеся в файле «sample.cue» в файлы с дорожками: «split-track01.flac», «split-track02.flac», «split-track03.flac» and «split-track04.flac».
Можно записать теги сразу во все полученные файлы:
cuetag sample.cue split-track*.flac

Утилита cuetag работает с форматами FLAC, Ogg и mp3.

Источник

Читать дальше…