September 23, 2006
[Linux] iPod と Amarok と Last.fm の連携
iPod で曲を再生すると,再生に関する情報として,再生回数と再生時刻が iPod 本体に記憶されます.Amarok-1.4_beta1 以降には,これらを読み出して,Amarok が管理する統計情報と同期し,さらにはそれらの情報を Last.fm 側に通知する機能が備わっています.1.4_beta1 以降,ということは,かなり昔から使用可能だったようですが,不覚にも私は今日まで気が付きませんでした.もちろん,Amarok 側のデザインがそれに気づきにくくなっているわけではありません.単純に私が見落としていただけのことです.
気づいたからには,試しに使ってみるしかありません.まずは再生回数がカウントされるかどうかを確認します.私は手元にある iPod nano (以降では nano と表記) で試しました.nano で曲を再生し,再生が終わったら,その nano を Amarok に接続します.すると,確かに Amarok 側に表示されている再生回数が増えると共に,Last.fm にその情報が送信された旨のメッセージも Amarok のステータスバーに表示されました.
同様にして,nano で曲の評価 (5段階) を変更した後に Amarok と同期すると,Amarok 側の評価も合わせて変更されました.
今度は,逆に Amarok 側で曲の評価を変更し,nano を接続すると... nano 側の評価も変更されました.素晴らしいです.Amarok がどんどん進化してゆきます.
September 10, 2006
[TeX関連] powerdot を使ってみる
今までプレゼンテーション用スライドを LaTeX を使って作成するために prosper を用いていましたが,私が新しい発表用のスライドを作るにあたって,それに改良を重ねた powerdot というものを試してみることにしました.
まずは CTAN からダウンロードして,適当な場所に展開します.
(/path/to/powerdot.zip に powerdot のアーカイブファイルがあると仮定) % cd ~/.texmf/tex/latex/ % unzip /path/to/powerdot.zip
これで ~/.texmf/tex/latex/powerdot 以下に powerdot のスタイルファイルと,スタイルファイルのソースファイル,およびドキュメントが展開されます.私はドキュメントとソースファイルは消しました.
なお,~/.texmf 以下に自分専用の LaTeX 関連ファイルを置く方法についてはユーザ専用の TeX 環境を独自に構築を参照してください.
powerdot を使用するためには,いくつかの依存スタイルファイルをインストールもしくはアップグレードする必要があります.
私の場合,xcolor は Gentoo の portage にありましたので,そちらを使用しました.
% sudo emerge xcolor
後で調べると,xkeyval も portage にあったのですが,当時は気づかず,CTAN のファイルをそのまま手動でインストールしました.今もそのままです.
さて,何か作ってみることにします.試しに以下のものを書いてみました.
\documentclass[size=14pt,orient=landscape,paper=screen,mode=present,display=slides,style=sailor,hlentries,hlsections,fleqn]{powerdot} \renewcommand{\kanjifamilydefault}{gt} \title{タイトル} \author{pakuchan} \date{September 10, 2006} \renewcommand{\baselinestretch}{1.3} \begin{document} \maketitle \begin{slide}{最初} \begin{itemize} \item 1st. \pause \item 2nd. \pause \item 3rd. \pause \end{itemize} \end{slide} \begin{slide}{次} \begin{itemize}[type=1] \item 1st. \pause \item 2nd. \pause \item 3rd. \pause \end{itemize} \end{slide} \end{document}
documentclass のオプション部については,powerdot のドキュメントを参照してください.
タイプセットは prosper の時と同様です.
% platex test.tex (中略) % dvips -z -f test.dvi (中略) % gs -sPAPERSIZE=a4 -dCompatibilityLevel=1.4 -dNOKANJI -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite "-sOutputFile=test.pdf" -c '.setpdfwrite <</NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats /Ryumin-Light /GothicBBB-Medium]>> setdistillerparams' -f test.ps *** unembeddable CIDFont: /GothicBBB-Medium %
gs に渡すオプションがやたら長いのは,フォント埋め込みをしないようにするためです (私が使っている gs には,taiji さん作成のパッチを適用しています).
ここまでで,prosper の時から変わったと感じたのは... オーバーレイされたスライドを作る際に \overlays を書かなくてよくなったこと (\pause を書くだけでよくなった) と,dvips に用紙サイズのオプションを渡さなくてよくなったことでしょうか.
できあがった PDF ファイルを Adobe Reader 7.0.8 で開いてみると... 結構 prosper との違いがわかります.以下に 3 枚のサンプル画像を示します.
左端にナビゲーション用とおぼしき見出しが並んでいることと,type=1 とした itemize 部分のうち,一部が淡色表示されるようになったことでしょうか.見出しはハイパーリンクになっているので,Adobe Reader 上でクリック等のアクションを起こすことで,そのページにジャンプすることができました.
良さそうなので,今回のプレゼンテーションスライドは powerdot で作ってみます.
September 9, 2006
[プログラミング] ダイナミックリンクのススメ
Static Linking Considered Harmful という文書がありました.プログラムを作成する際に,スタティックリンクではなくダイナミックリンクを使いましょう,という内容の主張が書かれています.私もこれに賛成です.
原文にはスタティックリンクをした際の問題点がセキュリティに関するものなどを含めて 7 点挙げられています.この中で最も私の身近にある問題点が,そこに書かれている 1 番目の問題点でしょう.以下にその部分を引用します.
fixes (either security or only bug) have to be applied to only one place: the new DSO(s). If various applications are linked statically, all of them would have to be relinked.
強調箇所 (強調筆者) が身近に感じた点です.スタティックライブラリを書き換える度に実行プログラム本体を再リンクするのは面倒です.これだけでもダイナミックリンクを使う十分な理由になるでしょう.
もちろん今頃になってこんなことを考えたわけではないのですが,こういった文書を読む度に,自分が今作っているプログラムを libtoolize したくなります.ライブラリが多いので時間があるときにやってみることにします.
September 8, 2006
[foobar2000] foobar2000 で記録した ReplayGain を Amarok で使用する
ReplayGain を計算あるいは適用する Amarok スクリプトが紹介されていました.スクリプトの ChangeLog によれば,バージョン 0.7.1 以降で foobar2000 が ID3v2 タグに記録した ReplayGain 情報を読めるようです.というわけで,インストールしてみました.
曲の再生時にボリュームが変化します.おそらく DCOP 経由で Amarok 本体のボリュームを調整しているのでしょう.
これで,Amarok と foobar2000 については ReplayGain が適用できました.あとは... 私が持っている iPod nano にも適用できれば OK です.
とはいえ,foobar2000 は ReplayGain を ID3v2 タグの TXXX フレーム (ユーザ定義フレーム) に記録しているので,iPod が読んでくれるはずはないと考えています.
その可能性があるとすれば,ID3v2.3 タグの RVAD フレームもしくは,ID3v2.4 タグの RVA2 フレームです.foobar2000 が TXXX フレームに書き込んだ情報を RVA2 フレームに書き込むツールを作れば実現できそうです.
もっともその前に,iPod が RVA2 を読むかどうかを調べてみる必要がありそうです.
September 5, 2006
[Linux] Kopete の Keep-Alive と Regnessem
私は Kopete を使用していますが,そのうち MSN Messenger 上の友人から「空のメッセージが送られる」という指摘を受けました.Kopete にパッチを当てれば何とかなるんだろうなぁ,と思ってはいたのですが,詳しい原因が分からぬまま時は過ぎ...
今になってようやく,空のメッセージが送られるのは Regnessem 使用者であることがわかりました (私自身も Regnessem を使用したところ,Kopete を使用している他のユーザから 50 秒おきに空のメッセージが送信されることを確認しました).
「50 秒」というのが Kopete のソースを追いかける手がかりになりそうです.あとは kopete-3.5.4 のソースを展開し,「50」や「50000」などのキーワードで検索すると... ありました.msnswitchboardsocket.cpp の 812 行目,862 〜 868 行目に,Keep-alive メッセージを送信するコードが記述されています.以下に該当個所を引用しておきます.
812: if(!m_keepAlive)
813: {
814: m_keepAliveNb=20;
815: m_keepAlive=new QTimer(this);
816: QObject::connect(m_keepAlive, SIGNAL(timeout()) , this , SLOT(slotKeepAliveTimer()));
817: m_keepAlive->start(50*1000);
818: }
862: if(!m_keepAlive)
863: {
864: m_keepAliveNb=20;
865: m_keepAlive=new QTimer(this);
866: QObject::connect(m_keepAlive, SIGNAL(timeout()) , this , SLOT(slotKeepAliveTimer()));
867: m_keepAlive->start(50*1000);
868: }
タイマーを使って 50 秒おきに Keep-alive メッセージを送っているようです.実際に送る関数 (slotKeepAliveTimer()) を見てみると... 次のようにコードが書かれています.
1100: if ( onlineStatus() != Connected || m_chatMembers.empty())
1101: {
1102: //we are not yet in a chat.
1103: //if we send that command now, we may get disconnected.
1104: return;
1105: }
1106:
1107:
1108: QCString message = QString( "MIME-Version: 1.0\r\n"
1109: "Content-Type: text/x-keepalive\r\n"
1110: "\r\n" ).utf8();
1111:
1112: // Length is appended by sendCommand()
1113: QString args = "U";
1114: sendCommand( "MSG", args, true, message );
どうやらチャットウィンドウが開いている状態でないと,Keep-alive メッセージは送信されないようにはなっていますが,1114 行目に sendCommand( "MSG", args, true, message );
と書いてあるので,おそらく普通のメッセージとして Keep-alive を送信しているのでしょう.試しに Regnessem 上で,Kopete ユーザのチャットウィンドウを閉じてみると... 確かにその人からの Keep-alive は来なくなります.
Content-Type: text/x-keepalive という MIME タイプを指定してはいますが,Regnessem からはこれが通常のメッセージであると見做してしまうようです.本家 MSN Messenger や Windows Live Messenger では Regnessem 相手にこのような現象が起こらないようなので,少なくとも Kopete のような Keep-alive メッセージは送っていないと判断し,ここは Kopete にパッチを当てて,この Keep-alive を抑制してみます.
パッチの当て方は至って簡単で,msnswitchboardsocket.cpp の 812 〜 818 行と,862 〜 868 行目をコメントアウトするだけです.
パッチを当てた Kopete を起動してみると,チャットウィンドウを開いたままの状態でも 50 秒おきに空メッセージが来ることはなくなりました.
次は,Regnessem を使用しているユーザがサインインしてオンラインになったとき,もしくは不可視状態からオンラインになったときに,Regnessem 側の会話ウィンドウ (もちろん相手は Kopete ユーザです) が開いてしまう,という点についても解決したいと思います.
動作から推測すると,Kopete 側において,コンタクトリストに登録されているユーザがオンラインになったときに,空の会話メッセージを送信しているような気がします.というわけで,Kopete のソースを追いかけて,コンタクトリスト上の相手のステータスが変化したときのイベントハンドラを探してみたのですが,途中で面倒になったので,もっと検索範囲を一気に絞りこみます.
おもむろに Wireshark (旧 ethereal) を起動して,MSN サーバとの通信をログに記録します.Regnessem 側にポップアップが表示されるところから考えて,MSG コマンドを送信しているはずです.ログ中に MSG がないかどうかを探すと... ありました.
MSG 2 D 595 MIME-Version: 1.0 Content-Type: application/x-msnmsgrp2p P2P-Dest: (相手側のメールアドレス) (この部分にも情報が書かれているが,ASCII 文字でないので省略) To: <msnmsgr:(相手側のメールアドレス)> From: <msnmsgr:(自分側のメールアドレス)> Via: MSNSLP/1.0/TLP ;branch={A0B93F34-746D-3161-122D-AD856249368A} CSeq: 0 Call-ID: {63F62291-626B-814E-35D2-6F2E98446455} Max-Forwards: 0 Content-Type: application/x-msnmsgr-sessionreqbody Content-Length: 99 EUF-GUID: {A4268EEC-FEC5-49E5-95C3-F126696BDBF6} SessionID: 144262341 AppID: 1 Context: MA (NULL)(NULL)(NULL)(NULL)(NULL)
以上のデータが送信されていました.あとはデータの断片を手がかりに Kopete のソースコードを検索すると... dispatcher.cpp の 79 〜 106 行目にそれらしきコードが見つかりました.
79: void Dispatcher::requestDisplayIcon(const QString& from, const QString& msnObject)
80: {
81: Q_UINT32 sessionId = rand()%0xFFFFFF00 + 4;
82: TransferContext* current =
83: new IncomingTransfer(from, this, sessionId);
84:
85: current->m_branch = P2P::Uid::createUid();
86: current->m_callId = P2P::Uid::createUid();
87: current->setType(P2P::UserDisplayIcon);
88: current->m_object = msnObject;
89: // Add the transfer to the list.
90: m_sessions.insert(sessionId, current);
91:
92: kdDebug(14140) << k_funcinfo << "Requesting, " << msnObject << endl;
93:
94: QString context = QString::fromUtf8(KCodecs::base64Encode(msnObject.utf8()));
95: // NOTE remove the \0 character automatically
96: // appended to a QCString.
97: context.replace("=", QString::null);
98: QString content =
99: "EUF-GUID: {A4268EEC-FEC5-49E5-95C3-F126696BDBF6}\r\n"
100: "SessionID: " + QString::number(sessionId) + "\r\n"
101: "AppID: 1\r\n"
102: "Context: " + context + "\r\n"
103: "\r\n";
104: // Send the sending client an invitation message.
105: current->sendMessage(INVITE, content);
106: }
強調部分が見付かったコードです.この関数の名前が requestDisplayIcon() であることから,おそらくはコンタクトリストの画像を要求しているコードと思います.
つまり,Kopete は,相手ユーザがオンラインになったときに,自動的に相手のコンタクトリスト画像を要求するメッセージを送信し,それを Regnessem が受け取って会話ウィンドウをオープンする,ということのようです.
Kopete の設定を変更してコンタクトリスト画像を要求しないようにすればいいのでしょうが,それは嫌なので,別な方法で解決する必要があります.
今日は力尽きたので,続きは次の機会にします.
September 1, 2006
[foobar2000] foo_uie_lyrics_panel で ID3 タグ内の歌詞を表示
iPod で歌詞を表示するために,Amarok + Lyrics ID3 スクリプトを使って曲ファイルの ID3v2.3 タグに歌詞を書き込んでいくと,foobar2000 でもそれを表示したいと思うのが人情.
foobar2000 Wiki で,それを叶えるためのコンポーネントが紹介されています.foo_uie_lyrics_panel と foo_uie_lyrics の 2 つが載っていたので,ここでは解説に従って,前者をインストールしました.
ID3v2.3 タグの USLT タグフィールドに書かれた歌詞をこのコンポーネントで表示するには,foo_uie_lyrics_panel の設定 (Preference を開き,Tools - Lyrics panel の順に辿る) で,"Search" タブにある "Lyrics sources" 欄に $meta(UNSYNCED LYRICS) を追加します.これで,曲を再生すると,タグに書き込まれた歌詞が表示されます.