はじめに
MPD(Music Player Daemon)に任意のデコーダを追加する仕組みを追加(移植)しました。
Generic Decoder
Raspberry Pi + RuneAudioで音楽を鳴らしてみる にて、MPDでmdxとかマイナーなサウンドファイルを鳴らしたいので続く、と書きました。
しかしながら、MPDで新しいサウンド形式に対応するためにはmpdを書きなおしてビルドする必要があります。これはメンテも含めて結構面倒くさいです。実際2年前にMDX pluginを書いたことがあるのですが、既にMPDのアップデートでリベースが単純には行きません。しかも適当に繋いだのでメモリリークがあるのかクラッシュすることもあり、そのときにはmpdごと飛んでいました。
良い解決策はないかと調べたら、Generic Decoderなるパッチの存在を知りました。
http://mpd.wikia.com/wiki/GenericDecoder
これは外部デコーダをパイプで繋げてMPDの再生に対応させるものです。これなら標準出力にPCMを流す汎用的なプレイヤを簡単に繋ぐことが出来ますし、別のプロセスで動くのでデコーダが多少不安定でも我慢できます。なんで素晴らしいパッチなんだ!
と思ったのですが残念ながら最新のMPDにはこのパッチは当たりませんでした。2007年のパッチなので7年前か…そりゃ当たるわけない。
しかしながら、MPDで新しいサウンド形式に対応するためにはmpdを書きなおしてビルドする必要があります。これはメンテも含めて結構面倒くさいです。実際2年前にMDX pluginを書いたことがあるのですが、既にMPDのアップデートでリベースが単純には行きません。しかも適当に繋いだのでメモリリークがあるのかクラッシュすることもあり、そのときにはmpdごと飛んでいました。
良い解決策はないかと調べたら、Generic Decoderなるパッチの存在を知りました。
http:/
これは外部デコーダをパイプで繋げてMPDの再生に対応させるものです。これなら標準出力にPCMを流す汎用的なプレイヤを簡単に繋ぐことが出来ますし、別のプロセスで動くのでデコーダが多少不安定でも我慢できます。なんで素晴らしいパッチなんだ!
と思ったのですが残念ながら最新のMPDにはこのパッチは当たりませんでした。2007年のパッチなので7年前か…そりゃ当たるわけない。
Generic Decoderの最新版へのリベース
ということで頑張って最新版へリベースしました。その中で気づいたこと、やったこと等を幾つかメモ。
差分はこちら。
https://github.com/mitsuman/MPD/commit/2a5dceee0d32fa60a1b150d1a290991adb8e1965
- ファイル名やクラス名などの様々なシンボルがリファクタリングの結果変わってる
- 名前は変われど基本的な構造は意外と変わっていない?意外とちょろいかも
- streamのdecodeのみでmdxで必要な肝心のfileのデコードの実装が無いことに気づく
- fileのデコードを実装する
- streamのデコードは個人的には要らないので今回は捨てる
- generic_decoderとgeneric_tagreaderを分けている意味がわからないので、generic_tagreaderを廃してgeneric_decoderにまとめる
- programに対してsuffixを渡す意味が分からないので廃止
- ファイル形式毎にscript分けたほうが独立性が高くて良いと思う
- 文字列からaudio formatへの変換関数が消えている…ひとまず44100:16:2に固定で
- 動くようになった感じがするけどやたら重いぞ?と思ったらパイプからの読み込みがなぜか敢えてノンブロッキングになっててビジーループになってる!意味不明なのでブロッキングとする
- mpdから起動したスクリプトは再生停止時にmpdからkillされます。このときスクリプトの中で起動したデコーダはパイプが壊れるためSIGPIPEシグナルでプロセスが死ぬはず。amd64 ubuntu12では死んでた。なのに、何故かraspi(rune audio)上だとスクリプトから起動したデコーダが生存してしまう。よく分からないのでスクリプト上でexecでデコーダを呼び、スクリプトとは別にプロセスが起動しないようにした
差分はこちら。
https:/
やり残してること
- stream対応
- audio formatの変更
- gettagの効率化
- シーク対応 (可能なら)
- コントリビュート (可能なら)
ビルド方法
git clone git://git.musicpd.org/master/mpd.git git checkout generic-decoder ./autogen.sh ./configure --enable-generic make make install
/usr/local以下にインストールされるので、それに合わせて設定を変えてください。
使い方
一例です。
mpd.confに
この場合、
例えばこんなふう。
mpd.confに
generic_decoder { suffix "mdx" pcm_format "44100:16:2" program "/usr/local/bin/decoder_mdx.sh" }を追加。これで拡張子がmdxのファイル(大文字小文字の区別なし)は/usr/local/bin/decoder_mdx.shを使ってデコードすることになります。
この場合、
/usr/local/bin/decoder_mdx.sh filerawdecode hoge.mdx | aplay -f cdで音がなるように/usr/local/bin/decoder_mdx.shを作る必要があります。
例えばこんなふう。
#!/bin/sh # mdx2wav from https://github.com/mitsuman/mdx2wav MDX2WAV=/usr/local/bin/mdx2wav ACTION="${1}" case "${ACTION}" in rawdecode | filerawdecode) INPUT="${2}" OUTPUT="${3}" $MDX2WAV "${INPUT}" ;; gettag) TAGNAME="${2}" INPUT="${3}" case "${TAGNAME}" in time) $MDX2WAV -m "${INPUT}" ;; title) $MDX2WAV -t "${INPUT}" | iconv -f SHIFT_JIS -t UTF-8 ;; *) exit 1 ;; esac ;; *) echo "$0 filerawdecode <inputfile>" >&2 echo "$0 gettag <tagname> <inputfile>" >&2 exit 1 ;; esac
最後に
というわけでMPDでmdxとかが聴けるようになりました。
標準出力を受けるのは汎用的でunix的で良いんだけど、シークとかに自然な感じでは対応しづらいよね。うーん、どうせなら頑張ってxmms2のプラグインを読めるようにする方が良かった説!
標準出力を受けるのは汎用的でunix的で良いんだけど、シークとかに自然な感じでは対応しづらいよね。うーん、どうせなら頑張ってxmms2のプラグインを読めるようにする方が良かった説!