2009年3月22日日曜日

Xdmxを使ったマルチディスプレイ



Xdmxを使うと、別々のコンピュータに接続されているディスプレイ同士を繋いでマルチディスプレイが実現できる。
試しに、普段使っていないサーバのディスプレイを活用してマルチディスプレイを実現した。
今回は、laptopでUbuntu8.04(Gnome)を、serverでDebian lenny(CUI)を実行しているものとする。
serverとlaptopをまたいで設定しなければならないので、serverを赤、laptopの端末を青で表記する。

サーバの設定

サーバに、Xを起動するためにxinit、X起動後の端末としてxterm、xhostでlaptopからのアクセスを許可するためにx11-xserver-utils、そして、X Window Systemのサーバであるxserver-xorg-coreをインストールする。
server% sudo aptitude install xinit xterm x11-xserver-utils xserver-xorg-core

そして起動するが、このコマンドはSSHなどではなく、serverのコンソール上で実行する必要がある。
でないと、以下の(失敗例)ように怒られる。
server% xinit -display :0
(失敗例) X: user not authorized to run the X server, aborting.
(成功すると、グラフィカル(笑)な表示に切り替わり、xtermのウィンドウが開く)


laptopからX Serverにアクセスできるように権限を追加(毎回やる必要があるらしい)
server% DISPLAY=:0 xhost +laptop

なお、サーバには環境変数をつけているが、X Serverで動いているxterm上で実行できる場合は必要ない。
私はサーバに接続するマウスを持っていないので、このようにディスプレイを指定した。
(マウスをxterm上に持っていかなければ、コマンドが打てない)

laptopの設定
Xdmxを、ウィンドマネージャを実際に動かすほう(laptop)にインストールする。ただじ、なぜかUbuntu8.04ではXdmxがリポジトリから削除されているので、以下のサイトからパッケージをダウンロードしてくる。
laptop% wget http://launchpadlibrarian.net/9590666/xdmx_1.3.0.0.dfsg-12ubuntu8_i386.deb
laptop% sudo dpkg -i xdmx_1.3.0.0.dfsg-12ubuntu8_i386.deb

dbusの権限を緩める
何かの用途でdbusを使っているようだが、設定されている制限がきつすぎることがあるらしい。
gnome-session後、以下のようなエラーが大量に出る。
** (nm-applet:5716): WARNING **: nma_dbus_init(): could not acquire its service. dbus_bus_acquire_service() says: 'Connection ":1.30" is not allowed to own the service "org.freedesktop.NetworkManagerInfo" due to security policies in the configuration file'
そういう場合は、/etc/dbus-1/system.d/nm-applet.confのdefaultセクションの「org.freedesktop.NetworkManagerInfo」のdenyになっているところをallowに変更し、デーモンを再起動。
laptop% sudo nano /etc/dbus-1/system.d/nm-applet.conf
<policy context="default">
# <deny own="org.freedesktop.NetworkManagerInfo">

# <deny send_destination="org.freedesktop.NetworkManagerInfo">
# <deny send_interface="org.freedesktop.NetworkManagerInfo">
<allow own="org.freedesktop.NetworkManagerInfo">

<allow send_destination="org.freedesktop.NetworkManagerInfo">
<allow send_interface="org.freedesktop.NetworkManagerInfo">
</allow>
laptop% sudo /etc/init.d/dbus restart
これでほとんどのdbus関連のエラーは出なくなったのだが、dbusが使われている要所要所でエラーが起こっている。セキュリティの心配もあるので、要調査。
参考
http://lists.freedesktop.org/archives/dbus/2007-January/006874.html

Xを終了

開いているディスプレイ番号を振っていけばいいので、本来こんな設定は必要ないのだが、GNOMEの場合は多重起動ができないそうなので、勝手にgnomeが立ち上がらないようにする必要がある。
Xfceなどを新たにインストールするのも手だが、とりあえずうまく動くか試してからのほうがロールバックが楽なので、Xを単に終了する。
sysv-rc-confは、各ランレベルで何を起動するかを指定することができるコマンドラインツールだが、「-」キーを押すとそのサービスが一時的に終了するようになっているので、これを利用する。
laptop% sudo aptitude install sysv-rc-conf
laptop% sudo sysv-rc-conf

gdmと書いてある行で-キーを押せばxが終了し、コンソールのログイン画面に飛ぶ。

デュアルディスプレイでgnomeを起動
二つのディスプレイを使ったX Serverの起動
以下のように、serverからlaptopのX Serverにアクセスできるようにしてから実行する
laptop% xhost +server
laptop% Xdmx :1 -display laptop:0 -display server:0 +xinerama &

エラーが出た場合、大抵の場合「〜オプションをつけたら?」といったメッセージが出ているので、それをつけて再度実行。
ちなみに、私は「-ignorebadfontpaths」をつけた。
gnome-screenを実行することで、二つの画面に渡ってgnomeが起動する。
laptop% gnome-session

もちろん、serverにはgnomeが入っている必要はない。
ちなみに、Xdmxを実行した時点でxtermなどがまったく立ち上がらないため、私は以下のようにしてgnomeを立ち上げた。
laptop% xhost +192.168.0.2 && Xdmx :1 -display localhost:0 -display 192.168.0.2:0 +xinerama -ignorebadfontpaths & sleep 5; gnome-session
ほか、自動起動スクリプトなどを書くべきだろうが、とりあえずはこれでよしとする。


所有しているVAIOのモニタをラップトップで使用しようとしたところ、コネクタが独自規格で接続できなかった。諦めていたのだが、Xdmxを使えば他のマシンのXサーバを使ってマルチディスプレイ環境を実現できることを知り、今回挑戦してみた。
また、今回は一度仮想マシンで実験して、うまくいってから実機で試してみた。当然だがこちらのほうがミスも少ないし、ドキュメントもより正確な物が書ける。今度からこれでテストをしよう、と思う。
一見うまくいったようだが、実はウィンドウを動かしたりするとかなり動作がもたつく(特に、SCIMの動きが絶望的)。さらにDirectXを使用したアプリケーションが動かない。まだクリアすべき問題は残されている。

2009年3月18日水曜日

wineビルドスクリプト「mkwine.sh」

私はできるだけパッケージ管理ツールを使うように心がけているのだが、wineだけはいつもコンパイルしている。というのも、
  • 開発が早いため、あるソフトを動かすためにはバージョンx.y.zが必要、ということが間々ある
  • 自作や拾い物のパッチを当てたい
  • 何か一つくらいソースコードいじったりしているといざと言うときに自慢できる
  • そもそも、Wineの開発を追うのが趣味
といった事情があるからだ。しかし、バージョンアップのたびにいつも同じような作業をするのは面倒極まりない。そこでスクリプトを書いて便利に使っていたのだが、今回大幅に機能強化し、多少は汎用性が上がったと思うので、公開してみる。

#! /bin/sh
CONFIGURE_OPTS=""

while getopts c:ip OPT
do
case $OPT in
"c" ) CONFIGURE_OPTS=$OPTARG ;;
"i" ) INSTALL="true" ;;
"p" ) PATCH="true" ;;
esac
done

shift $(($OPTIND - 1))

WINEVER=$1
DOWNLOAD_TMP="/tmp/wine-"$WINEVER".tar.bz2"

abort () {
echo $1
exit 1
}

if [ -e "wine-"$WINEVER ]
then
echo "Already wine-"$WINEVER" is exist. Compile start."
cd wine-$WINEVER || abort "error: move current directory to latest wine"
else
if [ -e $DOWNLOAD_TMP ]
then
echo "Already "$DOWNLOAD_TMP" is exist. Melt start."
else
echo "wine-"$WINEVER" isn't exist. Download start."
wget http://jaist.dl.sourceforge.net/sourceforge/wine/wine-$WINEVER.tar.bz2 -O $DOWNLOAD_TMP || abort "error: file download"
fi
echo "Start melt "$DOWNLOAD_TMP
tar jxf $DOWNLOAD_TMP || abort "error: decompress"
rm $DOWNLOAD_TMP
cd wine-$WINEVER || abort "error: move current directory to latest wine"
if [ $PATCH = 1 ]
then
for i in ../*.patch
do
patch -p 1 -R < $i || abort "error: patch " $i
done
fi
fi
./configure $CONFIGURE_OPTS || abort "error: executing ./configure $CONFIGURE_OPTS"
make depend || abort "error: make depend"
nice -n 19 make CC="ccache gcc" CXX="ccache g++" || abort "error: compiling"
echo "no errors, success to compile."
if [ $INSTALL = 1 ]
then
sudo make install || abort "install missing"
else
echo "please \`make install' for root to install wine for your system."
fi

(あまりシェルスクリプトは慣れていないので変な書き方になっているかもしれない)
例えばこれを書いている時点での最新版(1.1.17)をインストールしたいなら、
$ mkwine.sh 1.1.17
と実行すれば、
  1. wineの公式サイトから/tmp以下にwine-1.1.17.tar.bz2がダウンロードされ、
  2. カレントディレクトリに解凍、
  3. -pが指定されていればカレントディレクトリに置いてあるパッチを当てる
  4. ./configure; make depend; makeを実行
  5. -iが指定されていればmake installする
という、一通りの作業を自動化できる。最初はバージョンくらいしか指定できなかったのだが、だんだんパッチを当てるようになったりして大きくなってきた。パッチにバージョン番号を書いておいて当てる必要があるパッチを自動判別するとか、自動的に最新版を落としてくるとか。

# もうあったりして・・・?

2009年3月6日金曜日

pulseaudioでサウンドサーバ

うちのDebian lennyの入ったサーバにpulseaudioをインストールして、サーバに音を鳴らさせてみよう、と思った。最近じゃじゃ馬のpulseaudioを見事懐柔し、上機嫌になっていたのだが、サウンドの合成がやたらと重いことがあるので、ちょっと試しにやってみようと思ったのだ。どうせこのサーバ(toshia.dip.jp)、そんなにアクセスもないから、普段暇をしているし。
# aptitude install pulseaudio
aspell{a} aspell-en{a} avahi-daemon{a} bind9-host{a} dbus{a} dbus-x11{a}
dictionaries-common{a} fontconfig{a} fontconfig-config{a} gconf2{a}
gconf2-common{a} gnome-audio{a} gnome-icon-theme{a}
gstreamer0.10-pulseaudio{a} hal{a} hal-info{a} hicolor-icon-theme{a}
libasound2{a} libasound2-plugins{a} libaspell15{a} libasyncns0{a}
libatk1.0-0{a} libatk1.0-data{a} libavahi-client3{a}
libavahi-common-data{a} libavahi-common3{a} libavahi-core5{a}
libavc1394-0{a} libavcodec51{a} libavutil49{a} libbind9-40{a}
libcairo2{a} libcairomm-1.0-1{a} libcroco3{a} libcups2{a} libdaemon0{a}
libdatrie0{a} libdbus-1-3{a} libdbus-glib-1-2{a} libdirectfb-1.0-0{a}
libdirectfb-extra{a} libdns45{a} libenchant1c2a{a} libfaad0{a}
libflac8{a} libfontconfig1{a} libfreebob0{a} libgconf2-4{a}
libgconfmm-2.6-1c2{a} libglade2-0{a} libglademm-2.4-1c2a{a}
libglib2.0-0{a} libglib2.0-data{a} libglibmm-2.4-1c2a{a} libgsf-1-114{a}
libgsf-1-common{a} libgsm1{a} libgstreamer-plugins-base0.10-0{a}
libgstreamer0.10-0{a} libgtk2.0-0{a} libgtk2.0-bin{a} libgtk2.0-common{a}
libgtkmm-2.4-1c2a{a} libhal-storage1{a} libhal1{a} libhunspell-1.2-0{a}
libice6{a} libidl0{a} libiec61883-0{a} libisc45{a} libisccc40{a}
libisccfg40{a} libjack0{a} libjpeg62{a} libltdl3{a} liblwres40{a}
liblzo2-2{a} libmalaga7{a} libnotify1{a} libnss-mdns{a} libogg0{a}
liboil0.3{a} liborbit2{a} libpango1.0-0{a} libpango1.0-common{a}
libpci3{a} libpixman-1-0{a} libpng12-0{a} libpulse-browse0{a}
libpulse-mainloop-glib0{a} libpulse0{a} libpulsecore5{a} libraw1394-8{a}
librsvg2-2{a} librsvg2-common{a} libsamplerate0{a} libsexy2{a} libsm6{a}
libsmbios-bin{a} libsmbios2{a} libsndfile1{a} libsplashy1{a}
libstartup-notification0{a} libthai-data{a} libthai0{a} libtheora0{a}
libtiff4{a} libts-0.0-0{a} libvoikko1{a} libvorbis0a{a} libvorbisenc2{a}
libwnck-common{a} libwnck22{a} libx86-1{a} libxcb-render-util0{a}
libxcb-render0{a} libxcomposite1{a} libxcursor1{a} libxdamage1{a}
libxfixes3{a} libxft2{a} libxi6{a} libxinerama1{a} libxrandr2{a}
libxrender1{a} libxres1{a} myspell-en-us{a} notification-daemon{a}
padevchooser{a} paman{a} paprefs{a} pavucontrol{a} pavumeter{a}
pciutils{a} pm-utils{a} powermgmt-base{a} psmisc{a} pulseaudio
pulseaudio-esound-compat{a} pulseaudio-module-gconf{a}
pulseaudio-module-hal{a} pulseaudio-module-x11{a}
pulseaudio-module-zeroconf{a} pulseaudio-utils{a} radeontool{a}
ttf-dejavu{a} ttf-dejavu-core{a} ttf-dejavu-extra{a} ucf{a} uswsusp{a}
vbetool{a} x-ttcidfont-conf{a}
なんてことだ。一瞬Xでもインストールされるのかと思ったが、それだったら152個では済まない。一応確認してインストール。
そして、/etc/pulse/default.paの編集。
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.0.0/24
上記の一行を入れる(実際の追加は太字のみ)。LAN内からのアクセスを許可。
自分のユーザの準備
# usermod -G pulse,pulse-access,pluse-rt toshi
-- 再ログイン --
$ pulseaudio -D
なぜか起動しない。
いろんな文献を漁っていると、どうやらpulseaudioを使っている人はalsaも入れている。とりあえず入れてみた。
# aptitude install alsa-base alsa-utils alsaplayer alsa-conf
この後、なぜかサウンドカードが3つ(!?)検出されたり、/dev/dspが無くなって大変だった。
現在の状況は、なんとか/dev/dspが復活し、echo mikumiku > /dev/dspとかすると音が鳴るようになった。だけど、alsaplayerやpulseaudioを立ち上げると、その瞬間固まる。サーバにキーボードを直接つないでも反応はなく、サービスももちろん反応しない(Webサーバなんだけどな、一応)。でもなぜかalsamixerで音量変えたりは出来る。軽く乗ってるノイズの音量も変わってるし、/dev/dspに直接書き込んだら音鳴ってるし。
解決方法が分かったら書きます・・・。

↓今開いてるタブ

http://d.hatena.ne.jp/kakurasan/20081212/p2
http://d.hatena.ne.jp/kakurasan/20080905/p1
http://mlog.euqset.org/archives/debian-users/43288.html
http://pulseaudio.org/wiki/CLI
http://hide-t.vox.com/library/post/colinx%E3%81%A7pulseaudio.html
http://www1.tcnet.ne.jp/fmurata/linux/alsa.html

2009年3月3日火曜日

動画からMP3を抜き出す

よくやることだけど、形式によってやりかたがまちまちで困る。そこで、こんなスクリプトを書いた。
#! /usr/bin/perl

if($ARGV[0] =~ /\.swf$/){
system("swfextract -m $ARGV[0] -o $ARGV[0].mp3");
}
elsif($ARGV[0] =~ /\.(flv|mp4)$/){
system("ffmpeg -i $ARGV[0] -acodec copy $ARGV[0].mp3");
}
else{
print "なにこれぇ?"
}
これをnautilus-scriptsのディレクトリ(~/.gnome2/nautilus-scripts)に保存すると、右クリックで抜き出せる。swf, flv, mp4に対応している。
動画の整理はnautilusでサムネイルを見ながらやるから、それだったら抜きだしもnautilusからやったほうが直感的で楽なのでは、と思って作った。意外と、形式を気にせずに抜き出せるので重宝している。
ちなみに、正常に動かすためには
# aptitude install ffmpeg swftools
と実行して、必要なコマンドをインストールする必要がある(Ubuntu)。