Hatena::ブログ(Diary)

notes plastiques このページをアンテナに追加 RSSフィード

January 17(Sun), 2016

ASUS Chromebook C200MAでUbuntuを起動する

ASUS Chromebook C200MAを格安Linuxノートとして使う目的で約2万円で購入し、試行錯誤の結果やっとまともに使えるようになったのでその記録。

ChromebookはChromeOSというWWWブラウザChromeを利用することに特化したOSが搭載されている。
ChromeOSのカーネルLinuxなので色々なことができる。
Linuxディストリを使うという目的であれば2つの方法がある。

Linuxディストリchroot環境で実行する

これについては、croutonという完成度の高いツールが公開されているので、それを利用するのが良い。chroot環境でありながら、GUI環境まで提供されている。

Linuxディストリを生で起動する

chrubuntuというのがあるようなのだが、私の理解が正しければLegacy boot(普通のPCでのBIOSによる起動)ができる古い機種でしか利用できない。
C200MAでもLegacy bootを有効化する方法は存在するのだが、危険な作業をする必要がある。
http://www.matws.org/c300/
http://kazuhito-m.github.io/tech/2015/10/04/choromebook-c300ma-ubuntu-boot/

それは避けたいと色々調べた結果、これらを参考に起動することができた。
https://wiki.debian.org/InstallingDebianOn/Asus/C201
https://bbs.archlinux.org/viewtopic.php?id=185789
https://github.com/hanklords/chromebook-busybox

概要

普通のPCでOSを起動するのはHDDMBRを読み込むLegacy bootか、EFIバイナリが格納されたパーティションを読みこんで起動するEFI方式が一般的だ。
Chromebookはそのどちらでもない、corebootというものを利用しているそうである。
これは署名済みカーネルバイナリを焼きこんだカーネルパーティションを読み込んで起動するという方式のようだ。
そのため、UbuntuのようなLinuxディストリインストールするにはこのような機構を理解していないといけない。

試行錯誤の結果、下記の方法によってUbuntuを起動させることに成功した。
・最小構成debian環境を作成する
Grubのかわりに、この環境からkexecにより他OSを起動する。
UbuntuインストーラUSBを作成・修正・起動する
UbuntuインストーラUSBを一般的な手順で作成したあと、kexecで起動するためのスクリプトを作成し、debianから起動する
Ubuntuインストールし、Ubuntuを起動するためのスクリプトを作成する


作業では
Chromebook上のcrouton環境(以下crouton環境と呼ぶ)
・x86_64のUbuntu PC環境(以下PC環境と呼ぶ)
Ubuntuインストール先のSDカード
を必要とする。

手順

途中、面倒になったので書きかけです。リンク先など参考にしてみてください。

Chromebook上のcrouton環境

Googleで検索して以下等を参考に準備してください
http://qiita.com/yasuki/items/f6a8a350087517b0069b

SDカードパーティション作成

PC環境で行うことをおすすめする。rootで行う。

DEV=/dev/mmcblk1

# GPTとしてフォーマット
parted --script ${DEV} mklabel gpt
# ChromeOS用のGPTにする
cgpt create ${DEV}

# カーネルパーティションサイズは16MB固定のよう?
KERNEL_SIZE=32768
P1_SIZE="${KERNEL_SIZE}"
# Debian環境パーティションセクタサイズ 1GB相当
P2_SIZE=2097152
# Ubuntu環境パーティションセクタサイズ 適当に
P3_SIZE=39772093

P1_BEGIN=34
P2_BEGIN=`expr ${P1_BEGIN} + ${P1_SIZE}`
P3_BEGIN=`expr ${P2_BEGIN} + ${P2_SIZE}`

# Debian環境カーネルパーティション
cgpt add -t kernel -l debian_kernel -b ${P1_BEGIN} -s ${P1_SIZE} ${DEV}
# Debian環境パーティション作成
cgpt add -t data -l debian_root -b ${P2_BEGIN} -s ${P2_SIZE} ${DEV}
# Ubuntu環境パーティション作成
cgpt add -t data -l ubuntu_root -b ${P3_BEGIN} -s ${P3_SIZE} ${DEV}

blockdev --rereadpt ${DEV}

https://wiki.debian.org/InstallingDebianOn/Asus/C201

最小構成debian環境

まずはカーネルビルドする。
https://github.com/hanklords/chromebook-busybox#kernel
この記事では、バージョンが4.0-rc7を使っているが、私は3.?をビルドした。
とくに問題は起こっていない。

ビルドしたバイナリをvbutil_kernelで署名し、カーネルパーティションに書き込む。

ルートイメージを/dev/mmcblk1p2に作成する。

Ubuntuインストーラ環境

Ubuntu14.04.3のStartup Disk CreatorでインストーラUSBを作成する。

./syslinux/txt.cfg

kexec -l /mnt/casper/vmlinuz.efi --command-line "noprompt cdrom-detect/try-usb=true file=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd.lz --" --initrd=/mnt/casper/initrd.lz

Ubuntu環境

インストール後、そのままでは起動しないので
kexec -l $(readlink -f ${MNT}/vmlinuz) --command-line "BOOT_IMAGE=/$(basename $(readlink ${MNT}/vmlinuz) ) root=UUID=659bf19e-e80a-4243-bcab-8ecfc3d84c84 ro elevator=cfq" --initrd $(readlink -f ${MNT}/initrd.img) -d

kexec -l $(readlink -f ${MNT}/vmlinuz.old) --command-line "BOOT_IMAGE=/$(basename $(readlink ${MNT}/vmlinuz.old) ) root=UUID=659bf19e-e80a-4243-bcab-8ecfc3d84c84 ro elevator=cfq" --initrd $(readlink -f ${MNT}/initrd.img.old) -d

驚くべきことに、スピーカーの認識以外はちゃんと機能している。
機種によって相性良し悪しがあるそうなので、たまたま相性が良かったのだろうと思う。

スピーカーの認識

スピーカーの認識についても試行錯誤の結果やっと認識させることができた。
http://www.matws.org/c300/
このサイトによるとカーネルは4. 以上を使う必要があるので、最新版カーネルインストールする
apt-get update
apt-get install linux-generic-lts-wily
ChromeOS上の/lib/firmware/intel/fw_sst_0f28*をUbuntu環境の同じ場所にコピーする。
その後、fw_sst_0f28.bin-48kHz_i2s_masterをfw_sst_0f28.binへのシンボリックリンクとして作成する。
ln -s fw_sst_0f28.bin fw_sst_0f28.bin-48kHz_i2s_master
再起動後、alsamixerを起動し
・Left Speaker Mixer Left DAC
・Right Speaker Mixer Right DAC
のミュートを解除することで、音声が出力されるようになる。
https://wiki.archlinux.org/index.php/Advanced_Linux_Sound_Architecture#Unmute_with_alsamixer
https://wiki.ubuntu.com/Audio/Alsamixer



https://wiki.debian.org/InstallingDebianOn/Asus/C201
https://bbs.archlinux.org/viewtopic.php?id=185789

December 02(Tue), 2014

PDFに追記する方法

事務手続きで書類を提出するときに、PDFを印刷し、そこに手書きして提出するということがよくある。
コンピュータであらかじめテキストを入力しておくことはできないものか。
MacならPreview.appでできる。そうMacならね。
だけどMacの独自機能に頼るのはちょっと不安。(Macは好きだけどね。)
というわけでどうにか出来ないか調べてみた。


まず、途中で諦めた方法。(うまくできる方法はこの後に。)

PostScriptに変換して編集

GhostScriptでPSに変換できる。ただ普通に変換するとASCII85というエンコードをされていて、テキスト編集できない。
小一時間調べた所CompressPagesを無効化することによって読める形式で出力してくれるとわかった。

gs -o doc.ps  -dNOCACHE -sDEVICE=ps2write -dCompressPages=false doc.pdf

あとは、テキストエディタで編集。
だが、PostScriptはよくわからないのでどう編集すればよいのかさっぱりだった。
分かる人いないかなあ。

追記するPDFを作る

この方法は面倒だが、一応うまく行っている。
1ページしかない場合を想定する。

inkscapeで追記したいベクタイメージを作成する。そして、pdftkの機能によって元PDFと合成するという算段である。
postscript - overlay one pdf or ps file on top of another - Stack Overflow
inkscapeで追記するときは、元PDFのラスタイメージを下敷きにすることによって位置を正確に把握できる。

必要なツール:ghostscript, inkscape, pdftk

まず、PNG等のラスタ化したファイルを作る。

gs -o doc.png -dNOCACHE -sDEVICE=png48 -r300 doc.pdf

これはあくまで下敷き用画像なのでDPIは好みな値で構わない。

inkscapeで開く

inkscape doc.png

開くときに、画像をリンクするか埋め込むか聞かれるので、リンクを選択する。(あとで除去するため)

開いたら、画像を30%に縮小し、ドキュメントサイズもそれに合わせる。
この操作はしなくてもさほど問題は無いが、オリジナルのサイズを保ちたいのであれば行うこと。
今回300dpiで変換したが、dpiを変える場合は比率も変わる。例えば72dpiでは125%となる。

追記したいものを描く。

SVGとして保存。

テキストエディタにてSVGを開き、doc.pngをリンクしている<image>タグを探す。
それをコメントアウトあるいは削除する。

SVGPDFに変換する。

inkscape -z -f doc.svg -A overlay.pdf

pdftkにより合成する。

pdftk overlay.pdf background doc.pdf output out.pdf


Preview.appよりも細かく編集できるので、何かの時に役に立つかもしれない。

その他

PDFSharp
pyPDF
Foxit Reader
とりあえず書いておいた。

February 15(Sat), 2014

Nexus7 2012でchrootなdebianを構築する


前置き


突然ですが、私がNexus7 2012を購入した理由は、外出先でプログラミングSSHなどの作業がしたかったからです。
動画を見たかったという理由もありますが、それだけであればGalaxy Note SC-05Dを既に持っていたのでそれで事足ります。
ネットで検索してみると、Nexus7でネイティブUbuntuを動かしたという記事がちらほら見つかります。

もちろん私も試しました。期待していた以上に使えます。
問題は、PC用の画面表示なのでキーボードマウスがないとちょっと不便というところでしょうか。
それはまあ良いのですが、たとえばUbuntuは13.04より新しいのではサポートしないと表明していたり、12.04のイメージが無かったりという点が個人的には不満でした。debianもありませんし。
おそらくイチから作ることも出来るのだと思いますが、私の技術力では到底できそうもなさそうなので諦めていました。


ところで、ネイティブに動かす方法の他に併存して動かす方法もあります。
ご存知の通り、AndroidLinux Kernelを使っているので、UbuntudebianなどのバイナリAndroid上で動かせるのです。
仮想化とは違い、カーネルを共有し(詳しくないので語弊があるかも)Linux環境内でプロセスを動かします。
既存の方法であれば、

などがあります。

これとか参考になります。

Linux on Android, debian kit両方とも試しましたが、SSHできないだとか、ユーザーの作成、パスワード変更ができないなどの不具合がありました。
そのときはAndroid 4.4.2 KK KOT49Hを使っていたのですが、今思うにSELinuxだとかグループ設定だとかが悪さをしてそうです。SELinuxはPermissiveにしたりして試しましたがそれでもうまく行きませんでした。何かが悪さしているのでしょう。


そこでAndroidのバージョンを変えて試しました。結果から言うと、4.3 JWR66Yでは試した範囲ではダメで、4.2.2 JDQ39ではdebian kitでsqueezeがなんとか動きました。

ただ、貪欲な私は古いsqueezeではなくwheezyが使いたいと思いました。(Ubuntuもありですが、ちゃらいOSなので相性の問題が起こりやすそうと思い見送りました。)
ネイティブでイチからやるのはさすがに無理だと思いましたが、chrootによる環境構築がちらほら情報が見つかります。そこでトライしてみることにしました。


Debian環境の構築

chroot環境にDebian環境を構築します。普通にPCにdebianUbuntuインストールする方法は用意されていません。debootstrapというdebianの環境を構築するツールを使います。

このツールによる作業はfirst stageとsecond stageに分かれています。
first stageは別のマシンでも実行できます。armではなくx86なマシンでも構築できます。
second stageはインストール先マシンで行います。
その後はパッケージをインストールしたり設定できます。

これらのサイトの情報が役立ちました。

ところどころ上手くいかないところがあるので、私が行った手順を記します。

first stage

私はx86_64のUbuntu 12.04上でfirst stageを行いました。
debootstrapをインストールします

# on ubuntu as root
apt-get install debootstrap

debian環境を構築するためのディレクトリを用意します。

# on ubuntu as root
mkdir /path/to/dir

debootstrapのfirst stageを実行します。クロス環境用のコマンドです。

# on ubuntu as root
debootstrap --foreign --arch armhf wheezy /path/to/dir http://ftp.jp.debian.org/debian

ダウンロードしたりで少々時間かかります。

archの部分はARMの場合、armelとarmhfがあるようです。hfはHard Floatのことで、ハードウェア浮動小数演算が速いCPUではこちらのほうが良いらしい。古いARMではarmelが良いらしい。(ということは古いのでも一応動くのか??詳しくないので分かりません。)
variantというオプションもあります。省略した場合はminbaseになっているようです。


first stageで出来上がった /path/to/dir をNexus7に転送する。が、パーミッションを保つ必要があるので転送方法と、保存場所には注意すること。/sdcardに生で置くと良くない。
私はdebian.tarに固めてadbなどで転送し、/data/local/debian に展開した。
tarを使うのにbusyboxが必要。後の作業でも必要になるのでインストールしておこう。)

# on ubuntu root
cd /path/to/dir
tar cvf /some/dir/debian.tar .
adb push /some/dir/debian.tar /sdcard/

Nexus7上にて

# on nexus7 android as root
mkdir /data/local/debian
tar xvf /sdcard/debian.tar -C /data/local/debian


次はdebian環境用にandroidデバイスファイルなどをマウントする。
/proc, /sys, /dev, /dev/ptsをマウントする必要がある。
エラー処理を除けば、例えば/procについては

# on nexus7 android as root
mkdir /data/local/debian/proc
mount -o bind /proc /data/local/debian/proc

と実行すれば良い。
あと、/dataにexec,dev,suidを許可してマウントし直す。

# on nexus7 android as root
mount -o remount,exec,dev,suid /data

(mountの結果が前後で変わらないので必要なのか不明。。。これが嫌であればイメージファイルを作ってマウントする手法もある。サイズ固定が嫌なので見送った)


DNSサーバーの設定をコピーする。Google Public DNSが設定されていた。(ひょっとしてsecond stage後でないとダメ?記憶があやふや

# on nexus7 android as root
cp /etc/resolv.conf /data/local/debian/etc/


second stage

準備完了したので、とうとうchroot環境に入る。

# on nexus7 android as root
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
export HOME=/root
export SHELL=/bin/bash
chroot /data/local/debian /bin/bash -l

これでdebianになりました!と言いたいところですが、debootstrapのsecond stageを実行する必要があります。

# on nexus7 debian as root
/debootstrap/debootstrap --second-stage

少し時間がかかった後終了します。


apt-getのsources.listを編集しましょう。
chroot環境にはviemacsインストールされていないので、Android側から編集などするか、シェルで無理やり書き込むかしましょう。

deb http://ftp.jp.debian.org/debian/ stable main contrib non-free
deb-src http://ftp.jp.debian.org/debian/ stable main contrib non-free
deb http://ftp.jp.debian.org/ stable/updates main

シェルで書き込む場合は例えば

# on nexus7 debian as root
cat <<EOF >> /etc/apt/sources.list
deb http://ftp.jp.debian.org/debian/ wheezy main contrib non-free
deb-src http://ftp.jp.debian.org/debian/ wheezy main contrib non-free
deb http://ftp.jp.debian.org/debian/ wheezy-updates main
EOF

(2014/12/08 間違い修正)とか。


動作確認と、debianになった達成感を味わうためにアップデートをチェックしましょう。

# on nexus7 debian as root
apt-get update

ちゃんと動きましたか?
(私はresolv.confのコピーをし忘れてDNS解決できず失敗しました笑)


あとはタイムゾーンロケールの設定をしましょう。
タイムゾーンの設定

# on nexus7 debian as root
dpkg-reconfigure tzdata

ロケール

# on nexus7 debian as root
apt-get install locales
dpkg-reconfigure locales

参考まで日本語 265. ja_JP.UTF-8 UTF-8 を選んだ。


これで最低限は完了だ。


追記: dialog libreadline-dev apt-utilsをインストールしておいたほうが良い?

SSHとAvahiをインストール

私はsshとavahi-daemonを使いたかったので、この後インストールしました。xrdpも使いたいのですがまだうまくいっていません。
sshは簡単です。

# on nexus7 debian as root
apt-get install openssh-server

インストールされたら

 # on nexus7 debian as root
service ssh start

で起動します。(初回時はひょっとしたらapt-get中に起動されているかも?)


さて、avahi-daemonが曲者でした。avahiとはなにかを説明しておくと、ローカルのネットワーク機器でのマシン名からIPアドレスを解決するための仕組みです。市販ルーターを使っていてDNSサーバーをいじれない環境では便利です。Apple Bonjourとか調べてみてください。
まずホスト名を設定しましょう。grouperというホスト名にしました。
grouperとかnakasiとかって何のことなんですかね?)

# on nexus7 debian as root
hostname grouper

/etc/hostnameにgrouperと書き込む
/etc/hostsに

127.0.1.1 grouper

と書き込む。127.0.0.1でも良い?よくわからん。

avahi-daemonインストールします。どうやらdbusが必要なようです。(依存でインストールされるか確認していない。)

# on nexus7 debian as root
apt-get install dbus avahi-daemon

そしたらavahi-daemonを起動したくなりますが、ここで試しても失敗します。
Android側の特権グループにavahiユーザーを追加する必要があるようです。

# on nexus7 debian as root
groupadd -g 3003 aid_inet
adduser avahi aid_inet

失敗した場合は/etc/groupを編集するなど試してください。(よくわからんー\(^o^)/

aid_inet:x:3003:avahi

そしたら起動します。dbusが起動していないと失敗するようです。
(Nexus7を再起動したらavahiが動かなくなって、原因がわかるまで苦労した。。。初回はdbusが既に起動している。)

# on nexus7 debian as root
service dbus start
service avahi-daemon start

起動しましたか?
確認で、別のマシン(Macかavahiありのマシン)から

# on a machine with bonjour installed
ping grouper.local

など実行してみてください。名前解決できましたか?


あとはgnuplotとかg++とか入れて遊んでみようと思います。

chroot環境を終了する

起動したserviceをすべて終了し、bindしたディレクトリのマウントを解除する。
例えば

# on nexus7 debian as root
service ssh stop
service avahi-daemon stop
service dbus stop
exit
# on nexus7 android root
umount /data/local/debian/proc
umount /data/local/debian/sys
umount /data/local/debian/dev/pts
umount /data/local/debian/dev

(serviceをすべて終了する方法は無いのだろうか。sysvinitというのが関係あり??)


Misc



ipconfigが無い!
# on nexus7 debian as root
apt-get install net-tools
pingが無い!
# on nexus7 debian as root
iputils-ping

Emacsが変

adb shellからchrootで入った場合、EmacsでCtrl-Sがなぜか出来ない。
保存もCtrl-X SでXの後にCtrlを離さないとダメだったりする。謎。
SSHで入った場合は大丈夫。

特権グループ

adb上でidしてshellが所属してるgroupが出てきたのでめも
uid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1009(mount),1011(adb),1015(sdcard_rw),3001(net_bt_admin),3002(net_bt),3003(inet)

1023(media_rw)

一般ユーザーでsdcardに書き込みたいときはsdcard_rw(gid=1015)というグループを作って、それに追加すれば良いようだ。

インターネットに接続するには前述のaid_inetに追加している必要があるようだ。

こういう特権グループの一覧はどうやって調べればいいんだ?
/etc/groupみたいのはどこにあるんだ・・・?

おわり

お疲れ様でした。(自分へ)
これで外出先で思うように仕事が出来る環境ができました。
あ、でも持ち運びに適したマウスキーボードがまだ無い・・・


今回は4.2.2でやっとのことで動かせたが4.3 4.4.2では動くのだろうか。動かないとしたら何が原因なんだろうな。。。詳しい方いませんかね。


ちなみにうちには古いiPhone3Gがあるのだが、ホームボタンが効かないせいでJailBreakできない。
現在はSafari上でDDNS更新するだけのおもちゃとなっている。
JBできればcydiaSSHとかいろいろできるのになあ・・・


もう一つIDEOSも使われないで放置されているのだが、今回の方法でdebian環境を構築して超省電力(ただし超貧弱)サーバーを作ろうかとか考えている。
USBは5V 1Aまでで、それで充電できているので最高5Wの消費電力だ!!


安く買えてrootが取れるAndroidがあれば、この方法で超省電力サーバーが構築できて夢が広がりますね。

雑多メモ

VNCクライエントはbVNCというのが個人的には良い

gnomeはなぜか不具合ありなのでlxdeを使う

gnuplotでshmgetがうんちゃらとかエラーでる
XServer XDSLのページに書いてあったshmemのところを参考
https://github.com/pelya/cuntubuntu/tree/master/dist
ここからlibandroid-shmem.soをダウンロードし、
/etc/environment に

LD_PRELOAD=/path/to/libandroid-shmem.so

と追記する


dpiの変更は~/.Xresourcesに

Xft.dpi: 160

( xorg - High DPI @ lxde - Raspberry Pi Stack Exchange )

April 13(Sat), 2013

GracenoteのAPIを試してみた

iTunes等のCDプレーヤソフトはGracenoteが提供するデータベースによって曲名を取得している。だが、以前まで普通の個人がそのAPIを利用するのは敷居が高かった。*1ふと気になって調べてみたらなんと簡単に登録できるようになっていた。しかもWeb APIなるものまで提供されている。これは使ってみるしか無いと思って使ってみた。

今まではfreedbを用いていたが、いかんせん有志なのでデータベースが不足している。なのでGracenoteが使えたらありがたいのだ。クラシックのちょっとマイナーなのとか現代音楽とか雅楽のCDで試した限りではちゃんとトラック情報が取得できた。


Web APIはここに簡単に解説してある。: no title
どうやらClient IDなるものが必要らしいので、アカウント登録をしよう。

登録

アカウントの登録はここで行った。: no title
登録できたら、ここでログインしよう。: no title

準備

ログインするとMy Appsというページになる。Web APIの利用に必要なClient IDはそのためのAppを追加することで得られるので、右下にある"Add a new app"をクリックする。
Add Appのページになる。App Nameに自由に記入して"Create App"する。
するとMy Appsに戻り、下にAppが追加される。今追加したAppを開く。
App Detailsが表示される。必要なのは"Client ID for Mobile Client and Web API"だけなのでメモしておこう。

Web APIの利用にはClient IDに加えてUser IDが必要となる。
Web APIHTTPSを使ってXMLをPOSTすることでデータ要求し、XML形式で応答が返される。User IDを得るにもその手順を踏む。
ここ(no title)のRegistering a Deviceの項目に書いてあるが、以下のことを行う。

次のURLにUser IDを得るためのXMLをPOSTする。

XXXXXXXの部分はClient IDのハイフンの前の部分で置き換えること。

XMLの内容は以下になる。client_id_stringは各自のClient IDを。

<QUERIES>
    <QUERY CMD="REGISTER">
        <CLIENT>client_id_string</CLIENT>
    </QUERY>
</QUERIES>

例としてregister.xmlというファイル名だとしよう。

コマンドラインでこの要求を送信するのに、wgetcurlが使える。*2

# wget
wget --no-check-certificate --post-file=register.xml https://cXXXXXXX.web.cddbp.net/webapi/xml/1.0/

# curl
curl -d @register.xml https://cXXXXXXX.web.cddbp.net/webapi/xml/1.0/

すると次のような応答が返されるはずだ。

<RESPONSES>
    <RESPONSE STATUS="OK">
        <USER>user_id_string</USER>
    </RESPONSE>
<RESPONSES>

このuser_id_stringをメモしておこう。



TOCによりアルバムのトラック情報を得る

freedbでトラック名を得るときはTOC情報をからCDを探してくる。TOC情報とはCDの上で各トラックがどの位置からスタートしているかという情報のこと。そのfreedbと同じ事をGracenoteで行うことができる。

このページに書いてあることを行えばそれができる。

注意が必要なので、それについても記す。

次のXMLを送信しよう。あるCDのTOC情報のようだ。送信の手順はregister.xmlの時と同じである。

<QUERIES>
  <AUTH>
    <CLIENT>client_id_string</CLIENT>
    <USER>user_id_string</USER>
  </AUTH>
  <QUERY CMD="ALBUM_TOC">
    <MODE>SINGLE_BEST</MODE>
    <TOC>
      <OFFSETS>150 20512 30837 50912 64107 78357 90537 110742 126817 144657 153490 160700 175270 186830 201800 218010 237282 244062 262600 272929</OFFSETS>
  </TOC>
</QUERY>
</QUERIES>

OFFSETSのところにTOCを記述している。これについては後述する。
ちなみにOFFSETSに改行があるとうまくいかないようなので注意。

もとのページではSINGLE_BESTではなくSINGLE_BEST_COVERにしているが、カバー情報が無いCDでは問題が生じるのでSINGLE_BESTにする。*3

すると次のようなXMLが返される。

<RESPONSES>
 <RESPONSE STATUS="OK">
   <ALBUM>
      <GN_ID>15145216-E6E0EB71C036B10B0C1158CE602C5FAC</GN_ID>
      <ARTIST>Various Artists</ARTIST>
      <TITLE>O Brother, Where Art Thou?</TITLE>
      <PKG_LANG>ENG</PKG_LANG>
      <DATE>2000</DATE>
      <GENRE NUM="64773" ID="27131">Original Film/TV Music</GENRE>
      <TRACK_COUNT>19</TRACK_COUNT>
      <TRACK>
         <TRACK_NUM>1</TRACK_NUM>
         <GN_ID>15145217-94058D7FCB938ADFA97874409F9531B2</GN_ID>
         <ARTIST>James Carter &amp; The Prisoners</ARTIST>
         <TITLE>Po Lazuras</TITLE>
         <GENRE NUM="106221" ID="35985">Traditional Folk</GENRE>
      </TRACK>
<!-- 途中省略 -->
      <TRACK>
         <TRACK_NUM>19</TRACK_NUM>
         <GN_ID>15145235-2C101819521AA55ECCD07789F50A3F85</GN_ID>
         <ARTIST>The Stanley Brothers</ARTIST>
         <TITLE>Angel Band</TITLE>
         <GENRE NUM="75252" ID="31402">Bluegrass</GENRE>
      </TRACK>
   </ALBUM>
 </RESPONSE>
</RESPONSES>

お分かりの通り、ここにトラック情報などが記されている。めでたし。



TOC情報を得るには

cdrdaoでCDをリッピングすると.toc形式のファイルが得られる。これを料理する。cdrdaoについてよくわからない人は、前の記事を参照していただきたい。

TOC情報は.tocファイルの中の

  • FILE "image.bin" 19:43:19 16:21:63

といった行の右から二番目の時間情報を使う。この場合だと19:43:19だ。
これは

  • 分:秒:フレーム

という形式で記述されている。フレームという単位は1/75 秒のことだ。つまりフレーム表示に変換するには次のようになる。

  • (分*60+秒)*75+フレーム

OFFSETSに記述する際には150を加える必要がある。つまり2秒。よくわからないが、プリギャップとかいうのが関係しているとか。おまじないだと思っておこう苦笑
こうして得たフレームの配列をregister.xmlのOFFSETSのところにずらーと書くことになる。
注意するのは、Lead Outの位置も必要になることだ。
最後のトラックが

  • FILE "image.bin" 36:05:07 08:47:61

の場合、一番右が曲長の情報なので、位置と長さを加えたものをフレームに変換して加えておく。



自動でやってほしい

XMLパースとか面倒だよー*4という方はこちらをどうぞ。

cdrdaoの.tocをCD-TEXT付の.tocに変換する。CLIENT IDとUSER IDは取得してください。

標準入力で入力し、標準出力で出力する。例えば次のように使う。

./main.rb < image.toc > mod.toc

お約束だけれど、責任は負いません。




追記 2013/11/22: リンク切れ修正

*1:敷居が高いというか、登録フォームに記述して送信したらそのうち登録しますと返信がきて一ヶ月くらいまってみたら内容が足りませんといわれる始末。もちろん再度試したけれどダメ。サポートに連絡しても返事なし。という状況だった。

*2:恥ずかしいことにPOSTで生のファイルを送れるということを知らなくてどうするのかわからなかった。

*3:カバー情報が無いCDだとなぜかトラック情報が返されない。SELECT_EXTENDEDを使えば回避できるようだが今回は省略する。

*4:REXMLでパースできるよー

September 01(Sat), 2012

改札を何とかしてください

いつも不満に思うのが、スーパーのレジで待っている時間。
僕はパラサイト風情だからスーパーでは100円から高くても1000円ぐらいの買い物しかしないのだが、レジには沢山の食料品をカゴに入れたお客さんが並んでいることが多い。これはスーパーの存在意義からして当然だし、とやかく言うところではない。

しかし、なんで数百円の買い物しかしない自分がその後ろに並ばなくてはいけないのだろうか?*1
というよりも、もうちょっとすべての人が満足する方法がないのだろうか。
(僕の疑問が間違っていると思う人もいるかもしれない。そういう人は、学校とか塾とか考えてみたらよいと思う。一部の生徒に合わせて授業の進度を決められたらたまらないとあなたは思いませんか。)

これは海外ではすでに解決済みのことらしく、数品以下の買い物の人用に別のレジを用意しているそうだ。日本ではそんなの見たことが無い。


そういえば、最近こんな話もありました。

最近、いらっとしたのが自動改札。特に、出入兼用の自動改札。
僕が出ようとしている改札機に反対方向から人が入ってきたのだ。
別にそれだけだったら運が悪かったと思って我慢して、隣の改札に行けば良い。
でも、僕の出ようとしてた自動改札機の両隣はすでに入ってくる人が流れてて、入る人専用になっていたのだ。
そんなところに、僕の出ようとしてた自動改札機に人が入られたら僕が改札を出るにはずっと遠くの改札に行かなくてはいけなくなってしまうのだ。
どうしてくれるんだ!

日本人って礼儀正しいように見えるけど、ただルールに従ってるだけで、他人への思いやりあまりないよね。*2

…といろいろと愚痴りたいけれどここまでにして、どうしたらいいか考えてみる。


出入り兼用の改札なんてなくしちまえ。全部固定でいいんじゃないか?場所で不均一にしたくないなら交互にすればいい。という乱暴案。

人が出入しはじめた改札機の両隣は反対方向に限定してしまう。とか?
改札機の数メートル手前に人を検知したら、自動的に出入の配置を決めてしまい誘導させる。とか?

電車が着くちょっと前は入る人の優先度を上げて、電車が出発したあと少しの間は出る人の優先度をあげる、とか。

とにかく、なんとかして欲しい。

*1:そういえば、前に並んでるおばさんに順番譲ってもらったことがあった。

*2:というか、基本的に他人に思いやりや頭の良さを期待するのは間違いなのだろうか。