неділя, 25 січня 2009 р.

C or Do [mpd + icecast]

Налаштування Icecast описується у попередній статті.

Встановлення і налаштування mpd

Для інсталяції просто виконуємо наступну команду:
sudo apt-get install mpd

Робимо деякі зміни у файлі /etc/mpd.conf
######################## REQUIRED PATHS ########################
# You can put symlinks in here, if you like. Make sure that
# the user that mpd runs as (see the 'user' config parameter)
# can read the files in this directory.
music_directory "/media/sda9/music"
playlist_directory "/var/lib/mpd/playlists"
db_file "/var/lib/mpd/tag_cache"
log_file "/var/log/mpd/mpd.log"
error_file "/var/log/mpd/errors.log"
pid_file "/var/run/mpd/pid"
################################################################

Тут:
"music_directory" - каталог з музичними файлами, з яких потім будуть складатися програми.
"playlist_directory" - каталог, у якому mpd буде зберігати свої плей-листи.
"db_file" - файл, у якому mpd буде зберігати свою медіа-бібліотеку.
"log_file" і "error_file" - файли логів.

Далі потрібно налаштувати вивід звуку через Icecast:
# An example of a shout output (for streaming to Icecast):
#
audio_output {
type "shout"
name "My Shout Stream"
host "localhost"
port "8000"
mount "/mpd.ogg"
password "password1"
# quality "5.0"
bitrate "128"
format "44100:16:1"
user "password1" # optional
description "My Stream Description" # optional
genre "rock" # optional
public "no" # optional
}

Тут:
Параметри "host", "port" і "password" описують з'єднання з icecast.
Параметри "bitrate" і "format" задають якість потоку.

Кодування файлової системы і тегів в mp3-файлах:
filesystem_charset              "UTF-8"       
id3v1_encoding "CP1251"
Інші параметри можна залишити по замовчуванню.

На цьому настройка закінчена. Теперь потрібно проіндексувати каталог з музикою і запустити сервіси:
sudo mpd --create-db                                                                             
sudo /etc/init.d/icecast start
sudo /etc/init.d/mpd start

Зверніть увагу не те, що mpd обов'язково повинен стартувати після icecast.

Для керування програванням можна скористатися одним із клієнтів.
Використаємо консольний клієнт mpc
sudo apt-get install mpc

Додамо у плейлист всю базу пісень і запустимо програвання у довільному порядку
mpc add /                                                                   
mpc random on
mpc play

Після чого можете налаштувати ваш улюблений плеєр(я використовую Audacious) на програвання ogg-потоку з адреси http://<ваш_IP>:8000/mpd.ogg.

Бага

Я помітив, що mpd після зупинки/паузи, не реагує на команду play.
У файл логів /var/log/mpd/errors.log записуються наступні помилки:
[...]                                                           
Jan 25 15:01 : problems opening audio device while playing "world/n/Neversmile/2006.Миллиарды Минут/05-V_Otkrytuiu_Ranu.mp3"
Jan 25 15:01 : problems opening audio device while playing "world/b/Bloc Party/2008. Intimacy/08 - Zepherus.ogg"
Jan 25 15:02 : problems opening audio device while playing "world/а/Андерсон/2008.Словозброя/03 Споживач.ogg"
[...]


Недовгий пошук у гуглі привів до вирішення цієї проблеми.
https://bugs.launchpad.net/ubuntu/+source/mpd/+bug/155932
Якщо додати наступні рядки у /etc/mpd.conf, проблема зникає.

audio_output {
type "ao"
driver "null"
name "Dummy output"
}

$ cat /etc/issue
Ubuntu 8.10

$ uname -a
Linux linux 2.6.27-9-generic #1 SMP Thu Nov 20 21:57:00 UTC 2008 i686 GNU/Linux

$ mpd --version
mpd (MPD: Music Player Daemon) 0.13.2

Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>
This is free software; see the source for copying conditions. There is NO
warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Supported formats:
mp3 mp2 ogg oga ogg flac wav au aiff aif m4a mp4 mpc amf dsm far gdm imf it med mod mtm s3m stm stx ult uni xm

Supported outputs:
alsa ao oss pulse shout jack

Можливо в інших версія ця проблема відсутня.

Q: А до чого тут Ruby?
A: вам сюди http://librmpd.rubyforge.org
Інсталяції здійснюється командою:
sudo gem install librmpd

В архіві з librmpd у каталозі exampes є 2 досить хороших приклади роботи з mpd засобами ruby.
Більш детально про librmpd я розповім у одному з наступних дописів.

четвер, 22 січня 2009 р.

Icecast2 + ruby-shout

Icecast — вільне програмне забезпечення для організації потокового цифрового аудіомовлення. Його підтримкою займається Xiph.org Foundation.
Icecast є серверною програмою, яка може здійснювати роздачу цифрових потоків різних форматів, таких як Ogg Vorbis, Mp3, Theora, ААС, Aacplus і NSV. Власне передача даних здійснюється по стандартному протоколу HTTP, або по протоколу Shoutcast.
Icecast є аналогом програми Shoutcast компанії Nullsoft, проте має розвиненішу функціональність і підтримує більшу кількість форматів потоків. При передачі даних Icecast підтримує теги в Utf-8, що дозволяє організовувати трансляцію з кириличною анотацією.

Встановлення і налаштування Icecast2


Для встановлення Icecast2 просто запускаємо:
$ sudo apt-get install icecast2

Після цього ми повинні змінити /etc/icecast2/icecast.xml. Більшість значень по замовчуванню повинні працювати, але ви повині змінити паролі у секції <authentication>...</authentication>.

  • source-password це пароль який наша програма у майбутньому буле використовувати для зв'язку з сервером Icecast2;

  • admin-password це пароль який адміністратор буде використовувати у веб-інтерфейсі  Icecast2;

  • relay-password ми не будемо використовувати, але так чи інакше ви повинні змінити його.


[...]                              
<authentication>
<!-- Sources log in with username 'source' -->
<source-password>password1</source-password>
<!-- Relays log in username 'relay' -->
<relay-password>password2</relay-password>

<!-- Admin logs in with the username given below -->
<admin-user>admin</admin-user>
<admin-password>password3</admin-password>
</authentication>
[...]

Далі редагуємо /etc/default/icecast2 і встановлюємо ENABLE як true
[...]                                                      
ENABLE=true
[...]

Запускаємо сервер Icecast2:
$ sudo /etc/init.d/icecast2 start


Зараз ви можете у веб-броузері перейти за адресою http://127.0.0.1:8000/ і подивитись на веб-інтерфейс:


Встановлення ruby-shout


Встановлюємо пакети необхідні для ruby-shout:
$ sudo apt-get install libogg-dev libshout3-dev libspeex-dev libtheora-dev libvorbis-dev


libshout - це бібліотека для трансляції аудіо до icecast або shoutcast-сумісних серверів. На даний момент вона відтримує 2 формати аудіо і 3 протоколи.

Формати аудіо:

  • Ogg Vorbis

  • MP3



Протоколи:

  • HTTP

  • Audiocast

  • ShoutCast



ruby-shout це інтерфейс Ruby до libshout. Він дозволяє програмам на Ruby легко відправляти дані до icecast сервера і управляти мета-інформацією про потік.

Для інсталяції ruby-shout просто виконуємо:
$ sudo gem install ruby-shout


Приклад


Скрипт зчитує звукові дані з вхідного файлу і відправляє їх icecast серверу без resampling.
#!/usr/bin/ruby                  

# Stream all the files given on the commandline to the Icecast server on
# localhost.

require 'rubygems'
require 'shout'

BLOCKSIZE = 16384

s = Shout.new
s.host = "localhost"
s.port = 8000
s.mount = "/example.ogg"
s.format = Shout::VORBIS
s.user = "source"
s.pass = "password1"
s.name = "Example Radio"
s.description = "Powered by Ruby/#{VERSION}, ruby-shout/#{Shout::version}"
s.genre = "Rock"

s.connect

ARGV.each do |filename|
File.open(filename) do |file|
puts "sending data from #{filename}"
m = ShoutMetadata.new
m.add 'filename', filename
s.metadata = m
while data = file.read(BLOCKSIZE)
s.send data
s.sync
end
end
end

s.disconnect


Посилання


неділя, 18 січня 2009 р.

I'm alive! - 2


Цей пост від свого попередника відрізняється хіба що фоткою :). Всіх з Новим 2009 Роком!

P.S. У зв'язку з тим, що сайт infostore був закритий всі посилання на книжки, які я раніше викладав у цьому блозі були втрачені :(.


P.P.S. Документацію і книги по Ruby on Rails а також веб технологіям можна скачати з RubyClub.ua.

субота, 17 січня 2009 р.

Mechanize + вКонтакте

Цей допис несе навчально-практичний характер. На прикладі бібліотеки Mechanize я продемонструю як просто можна серфити веб-сторінками.
наш простий скрипт буде виконувати наступні дії:

  • Авторизація на сайті ВКонтакте

  • Зчитування кількості нових повідомлень і фотографій


І все це без використання веб-броузера.
Далі трохи теорії.

Mechanize використовується для автоматизації взаємодії з веб-вузлами. Mechanize автоматично запам'ятовує і відсилає куки(cookies), слідує за перенаправленнями(redirects), може переходити по лінках. Може використовуватись для заповнення форм. Крім того Mechanize тримає в історії список сайтів, які ви відвідали.
А для синтаксичного розбору html використовує nokogiri.

А тепер власне сам скрипт. У якості параметрів він приймає е-мейл і пароль. На виході - кількість нових фотографій і повідомлень. Крім того у скрипті передбачена реакція на невірний логін/пароль.
Це лише невелий приклад і можливість розширення обмежується тільки вашою фантазією.

require "rubygems"                                                          
require "mechanize"

$KCODE = "UTF8"

a = WWW::Mechanize.new {|agent|
# WWW::Mechanize::AGENT_ALIASES
agent.user_agent_alias = 'Linux Konqueror'
# VKontakte refresh after login
agent.follow_meta_refresh = true
}

a.get('http://vkontakte.ru/') do |home_page|
# home_page.links.each{|link| puts link.text}
# home_page.forms.each{|form| puts form.name}
singin_page = a.click(home_page.links_with(:text => 'Login').first)
my_page = singin_page.form_with(:name => 'login') do |form|
form.email = ARGV[0]
form.pass = ARGV[1]
end.submit
if my_page.title == 'VKontakte | Login'
puts "Such an e-mail address is not registered or an incorrect password is entered"
end
#pp my_page

# <div id="sideBar">
# <ol id='nav'>
# <li><a href='mail.php?id=13327146&41867'>My Messages</a></li>
# </ol>
# </div>
#
# Mix and match
messages = my_page.search('div.ol.li.a', '//div[@id="sideBar"]/ol[@id="nav"]/li/a').each do |link|
case link.content
when /My Messages/
messages = link.content.match(/^(My Messages)($)?( \((\d+)\)$)?/)[4] || 0
puts "Messages: #{messages}"
when /My Photos/
photos = link.content.match(/^(My Photos)($)?( \((\d+)\)$)?/)[4] || 0
puts "Photos: #{photos}"
end
end
end

понеділок, 2 червня 2008 р.

RubyOnRails 2.1

Стала доступна версія 2.1.0.

Основні нововведення:
  • Підтримка часових зон.
  • Відстежування "брудних" об'єктів (і, як наслідок, динамічне оновлення ActiveRecord).
  • Можливість задати залежності від gem-ів.
  • Інтеграція плагіна has_finder (тепер named_scope).
  • UTC-штампи для міграцій.
  • Покращене кешування.

>>> Подробиці.

Мій ~./vimrc

Цей допис не буде описувати структури конфігураційного файлу .vimrc.

Можливості:
  • ідентифікація типу файлу;
  • підстітка синтаксису;
  • заміна табуляції пробілами;
  • зміна кодування файлу для відкриття/зберігання;
  • зміна мови розкладки клавіатури;
  • перевірка орфографії;
  • статус-стрічка з інформацією про поточний файл;

Словники для перевірки орфографії можна скачати з сайту ftp://ftp.vim.org/pub/vim/runtime/spell/. Помістити необхідні файли *.spl в /usr/share/vim/vim70/spell/ .

set nocompatible          " We're running Vim, not Vi!
syntax on " Enable syntax highlighting
filetype plugin indent on " Enable filetype-specific indenting and plugging

set tabstop=2
set shiftwidth=2
set expandtab

set fileencodings=utf-8,cp1251,cp866,koi8-u
set encoding=utf-8
set termencoding=utf-8
set statusline=%<%f%h%m%r%=format=%{&fileformat}\ file=%{&fileencoding}\ spell=%{&spelllang}
set laststatus=2

" <F7> File fileformat (dos - <CR> <NL>, Unix - <NL>, mac - <CR>)
map <F7> :execute RotateFileFormat()<CR>
vmap <F7> <C-C><F7>
imap <F7> <C-O><F7>
let b:fformatindex=0

function! RotateFileFormat()
let y = -1
while y == -1
let encstring = "#unix#dos#mac#"
let x = match(encstring,"#",b:fformatindex)
let y = match(encstring,"#",x+1)
let b:fformatindex = x+1
if y == -1
let b:fformatindex = 0
else
let str = strpart(encstring,x+1,y-x-1)
return ":set fileformat=".str
endif
endwhile
endfunction

" <F8> File encoding for open
" ucs-2le - MS Windows Unicode encoding
map <F8> :execute RotateEnc()<CR>
vmap <F8> <C-C><F8>
imap <F8> <C-O><F8>
let b:encindex=0
function! RotateEnc()
let y = -1
while y == -1
let encstring = "#koi8-r#cp1251#8bit-cp866#utf-8#ucs-2le#"
let x = match(encstring,"#",b:encindex)
let y = match(encstring,"#",x+1)
let b:encindex = x+1
if y == -1
let b:encindex = 0
else
let str = strpart(encstring,x+1,y-x-1)
return ":e ++enc=".str
endif
endwhile
endfunction

" <Shift+F8> Force file encoding for open (encoding = fileencoding)
map <S-F8> :execute ForceRotateEnc()<CR>
vmap <S-F8> <C-C><S-F8>
imap <S-F8> <C-O><S-F8>
let b:encindex=0
function! ForceRotateEnc()
let y = -1
while y == -1
let encstring = "#koi8-r#cp1251#8bit-cp866#utf-8#ucs-2le#"
let x = match(encstring,"#",b:encindex)
let y = match(encstring,"#",x+1)
let b:encindex = x+1
if y == -1
let b:encindex = 0
else
let str = strpart(encstring,x+1,y-x-1)
:execute "set encoding=".str
return ":e ++enc=".str
endif
endwhile
endfunction

" <Ctrl+F8> File encoding for save (convert)
map <C-F8> :execute RotateFEnc()<CR>
vmap <C-F8> <C-C><C-F8>
imap <C-F8> <C-O><C-F8>
let b:fencindex=0
function! RotateFEnc()
let y = -1
while y == -1
let encstring = "#koi8-r#cp1251#8bit-cp866#utf-8#ucs-2le#"
let x = match(encstring,"#",b:fencindex)
let y = match(encstring,"#",x+1)
let b:fencindex = x+1
if y == -1
let b:fencindex = 0
else
let str = strpart(encstring,x+1,y-x-1)
return ":set fenc=".str
endif
endwhile
endfunction

" Russian support | CTRL+^
set keymap=russian-jcukenwin
" by default - latin keymap
set iminsert=0
" by default - latin keymap for search
set imsearch=0


" ftp://ftp.vim.org/pub/vim/runtime/spell/
if version >= 700
" По замовчуванню перевірка орфографії виключена.
setlocal spell spelllang=
setlocal nospell
function ChangeSpellLang()
if &spelllang =~ "en_us"
setlocal spell spelllang=ru
elseif &spelllang =~ "ru"
setlocal spell spelllang=uk
elseif &spelllang =~ "uk"
setlocal spell spelllang=en_us,ru,uk
elseif &spelllang =~ "en_us,ru,uk"
setlocal spell spelllang=
setlocal nospell
else
setlocal spell spelllang=en_us
endif
endfunc
" map spell on/off for English/Russian
map <F11> <Esc>:call ChangeSpellLang()<CR>
endif


Після перезапуску, Vim буде мати наступний вигляд:

субота, 24 травня 2008 р.

Monty Hall problem



# Парадокс Монті Холла (Monty Hall) - одна з відомих задач теорії ймовірності, рішення якої, на перший погляд
# суперечить здоровому глузду. Завдання формулюється як опис гіпотетичної гри, заснованої на американському телешоу
# «Let’s Make а Deal», і названа на честь ведучого цієї передачі. Найбільш поширене формулювання цього завдання,
# опубліковане в 1990 році в журналі Parade Magazine, звучить таким чином:
#
# Уявіть, що ви стали учасником гри, в якій вам потрібно вибрати одну з трьох дверей.
# За однією з дверей знаходиться автомобіль, за двома іншими дверима — кози. Ви вибираєте одну з дверей, наприклад, номер 1,
# після цього ведучий, який знає, де знаходиться автомобіль, а де — кози, відкриває одну з дверей, що залишилися,
# наприклад, номер 3, за якою знаходиться коза. Після цього він питає вас, чи не бажаєте ви змінити свій вибір і вибрати двері номер 2.
# Чи збільшаться ваші шанси виграти автомобіль, якщо ви приймете пропозицію ведучого і зміните свій вибір ?
#
GAMES = 10000
DOORS = [1, 2, 3]
stay_win = switch_win = 0

def choice(arr)
arr[rand * arr.length]
end

puts "Граємо #{GAMES} ігор..."
GAMES.times {
prize_door = choice(DOORS)
chosen_door = choice(DOORS)
opened_door = choice(DOORS - [prize_door, chosen_door])
switch_door = choice(DOORS - [chosen_door, opened_door])
stay_win += 1 if chosen_door == prize_door
switch_win += 1 if switch_door == prize_door
}

puts "Відсоток виграшів із стратегією зміни вибору становить: #{(switch_win.to_f / GAMES) * 100} %"
puts "Відсоток виграшів із стратегією не зміни вибору становить: #{(stay_win.to_f / GAMES) * 100} %"


Граємо 10000 ігор...
Відсоток виграшів із стратегією зміни вибору становить: 66.23 %
Відсоток виграшів із стратегією не зміни вибору становить: 33.77 %

вівторок, 25 березня 2008 р.

I'm alive!


Згадав про існування такого невеликого свого творіння. Давненько сюди не писав, тай узагалі забив на програмування.
Ні строчки коду за останні 2 місяці :(.
З головою пірнув у адміністрування і "енікейство". І тепер я спокійний: програмування залишиться для мене хобі, яке буде приносити мені моральне задоволення.

По трохи починаю відходити від усіх тих подій.
По трохи починаю звикати до нових умов.
По трохи починаю повертатися до розміреного життя.

Не я такий, життя змусило...

З самого початку цей блог задумувався як збірка думок, новин, матеріалів про Ruby і околорубінові теми. Настав час порушити це правило :). Вони ж для того і створенні. Вводжу новий тег [life].

понеділок, 21 січня 2008 р.

Rubular

Rubural - це новий онлайновий редактор регулярних виражень (regular expression) для Ruby. Дуже зручна річ для тестування. Особливо корисною буде для тим хто тільки починає знайомитись з такою потужною штукою як регекспи!