MPD(Music Player Daemon)の日本語化パッチと、lcd4linux・MPDプラグインのカタカナ表示対応版を用いて、Linuxで英数・カタカナ表示のキャラクタディスプレイ付きミュージックサーバを構築

Last-modified: 2015-12-11 (金) 23:48:36

(2015-12-9)mpd0.19系用パッチを作成しました。mpd0.18系用パッチも更新しました。
(2015-7-10)最近、自宅Linux環境をMint 13からMint17.2(最新環境)に変更しました。
Mint17.2付属のmpdのバージョンは0.18です。少々ファイル構成が変わり、0.15系用のパッチが適用できなくなっていたので0.18系用のパッチを作成しました。下記のリンクからダウンロードして下さい。


本ページ掲載のMPD(Music Player Daemon)の日本語化パッチは、音楽ファイル内のタグに含まれる日本語の文字コードをWindows標準のShiftJISのまま(手をつけずに)、MPDクライアント画面上に正しく日本語を表示する為のものです。
音楽ファイルのタグの文字コードがUTF16とかEUCとかJISの場合はそもそも適用外です(殆どそんなケースはありませんけど)。
また音楽ファイルをMPDやLinux上でのみ使用する場合は、パッチをあてず、タグの文字コード自体をタグ編集ソフトでUTF-8に変更してしまうという手法を採っている方もいます(私がmpd0.18系用パッチを作らない間に仕方なくそうした方もいるでしょう)。ただ、私はこの手法は決して採りません。手持ちの携帯プレーヤーがSJISタグにしか対応してないんですが、PC(Linux)用と携帯プレーヤー用みたいに同じ音源のファイルを二通り持ちたくないからです。


初出 2011-2-15
最終更新 2015-12-9
LCD2USB [tip]
 

MPDを私が推すのは、MPDがクライアントサーバーモデルを採用しているからです。ファイルサーバを音楽サーバにする用途にも向いています。デーモン(サービス)が常時稼動しているのでリモートから操作する用途にも非常に向いています。実際に非常に多種類のリモートから操作できるクライアントアプリが存在します。またIcecast2と連携させてストリーミングサーバを構成することもできます。もちろん言うまでもなく1台のPC上でサーバーとクライアントの両方を動かすこともできます。

 

本ページでは、こっちのページで「Windows」+「Winamp」+「LCD Smartie」+「LCD2USB」+「USB マイクロマルチコントローラ(MMC)を使って実現している以上のことを、「Linux」+「MPD」+「lcd4linux」+「lcd4linux・MPDプラグイン」+「LCD2USB」+「MMC」を使って実現しています。まあMMCは個人的な好みと言えるでしょう。

 

Linuxプログラマーを始め、LinuxをメインOSとしている方には是非お薦めしたい環境です。また、プレイリストは標準でWindowsやweb画面からリモート管理することもできるので、Linuxファイルサーバをミュージックサーバ兼用とすることもお薦めです。

使っているもの説明
Music Player Daemon(MPD)音楽ファイルを管理し、音楽を再生するデーモン(サービス)
各種MPDクライアントWindows用、携帯用、Linux用等
MPDの日本語化パッチ事実上、mt-daapd用の流用
lcd4linux小型(キャラクタ)液晶ディスプレイ表示用デーモン
lcd4linux MPD plugin自分で修正したもの修正前は使えない代物でした。修正の上、いろいろと自分にとって便利に仕立てました。
LCD2USB楽曲情報表示用・小型・キャラクタ液晶ディスプレイ
USB マイクロマルチコントローラUSB接続・専用操作キー(ボタン)
 

楽曲情報表示用・小型キャラクタ液晶ディスプレイ(LCD2USB)に表示される内容

専用キャラクタ液晶ディスプレイは英数とカタカナが表示できるのでかなり役に立ちます。
16x2ディスプレイを用いた場合の表示例をいくつか示します。

 

たとえば1行目は、

45/135 ビートルズ - アビーロード - 9/17 You Never Give Me Your Money

がスクロールするといった感じになります。先頭はプレイリスト内の現在の再生位置を表しています。id3ヘッダの全角カタカナを半角カタカナに変換して表示します。 (※この曲の情報をわざわざカタカナで入力する人は殆どいないと思います(笑)。あくまでサンプルです。)
2行目は、

2:15/4:03    

みたいな表示になります。現在再生中の「曲の経過時間/曲の長さ」です。再生を一時停止している間は「/曲の長さ」の部分に現在時刻を表示します。
mpd_and_lcd4linux_mpd_plugin_1_s.jpg
再生中はこんな感じです。周辺の色が少し濃いのは保護シートが浮いているからです。表示領域が狭いと感じる人は20x4行液晶を使って下さい。

 

あるいは、id3ヘッダがなかったりすると、かわりにファイル名を用いて、
たとえば1行目は、

5/30 20101231_machiyama_pate

がスクロールするといった感じになります。ファイル名の全角カタカナも半角カタカナに変換して表示します。
2行目は上と同じです。

 

また、SHOUTcastみたいなwebラジオの場合は、曲長の概念がないので、
たとえば1行目は、

28/30 James Morrison fet Nelly Furtado: Broken Strings

がスクロールするといった感じになります。現在再生中の曲名が表示されます。
2行目は、

5:05:46 14:30:32

みたいな表示になります。左側はそのチャンネルの再生開始からの経過時間です。右側には現在時刻を表示します。
mpd_and_lcd4linux_mpd_plugin_2_s.jpg
こんな感じです。周辺の色が少し濃いのは保護シートが浮いているからです。表示領域が狭いと感じる人は20x4行液晶を使って下さい。

 

1行目の書式を示します。

項目
1カレントプレイリスト中の現在再生位置必ず表示される
2/必ず表示される
3カレントプレイリストの総項目数必ず表示される
4スペース必ず表示される
5アーティスト名入力されていれば、引数が0,2,4,6の場合に表示
6スペース・ハイフン・スペースアーティスト名が表示される場合に表示される
7アルバム名入力されていれば、引数が0,1,4,5の場合に表示
8スペース・ハイフン・スペースアルバム名が表示される場合に表示される
9トラック入力されていれば、引数が0,1,2,3の場合に表示
10スペーストラックが表示される場合に表示される
11タイトル名もしくはファイル名必ず表示される

※「項目1~3は2行めに表示した方がいいんじゃないか」と思う方も多いと思います。そうしないのは実はlcd4linuxの制限(仕様)が関係しています。

MPDの日本語化(ShiftJIS/UTF-8両対応)パッチ

一から自前で作成したわけではなくて、殆どmt-daapd用の日本語パッチのコピペです。私がやったことは、どこにペーストすべきかを調べただけと言えます。この追加修正も加えてあります。

 

元のパッチに含まれていた、ファイル名(ファイルシステム)の文字コード変換機能は省いてあります。もう今はファイルシステムにutf-8以外の文字コードを使用している環境は殆どないと思います。

 

パッチの内容はこちら
ダウンロード filempd-0.19.11-cp932.patch  Ubuntu 15.10環境で作成しました。

 

ダウンロード filempd-0.18.7-cp932.patch  2015年12月にLinux Mint 17.2環境で作成しました。Ubuntu 14.04以降で適用できると思われます。

 

ダウンロード fileold.mpd-0.18.7-cp932.patch  2015年7月に多分Linux Mint 17.2環境で作成しました。

 

ダウンロード filempd-0.15.4-cp932.patch  Ubuntu 10.04環境で作成し、Linux Mint 13環境でも適用できました。

 

パッチを適用した(シフトJISタグに対応した)MPDを作成する手順

ここではDebian、Ubuntu系での手順を示します。

# apt-get build-dep mpd
$ mkdir hogehoge; cd hogehoge
$ apt-get source mpd
$ cd mpd-*

ここでパッチをあてます。このディレクトリ内であてるなら「patch -p1」、srcディレクトリ内であてるなら「patch -p2」です。

 

環境によって以下のいずれかを使用して下さい。
多少のバージョン違いによる行ズレはpatchコマンドが対応してくれます。
ダウンロード filempd-0.19.11-cp932.patch
ダウンロード filempd-0.18.7-cp932.patch
ダウンロード fileold.mpd-0.18.7-cp932.patch
ダウンロード filempd-0.15.4-cp932.patch

 

あとは普通です。
私の場合は、

$ dpkg-buildpackage -rfakeroot -uc -nc

あとは上のディレクトリにできている筈のdebパッケージをインストールして下さい。

# dpkg -i mpd_*.deb

です。

 

(2011-5-29追記)これを書かないとLinux初心者には不親切だと思うので追記しておきます。パッチをあてる前はデータベースにデータを収納する段階で既に文字化けを起こしています。ですからこの時点でサービスを停止して過去に作成されているMPDのデータベースファイルを一旦削除して下さい。デフォルトでは/var/lib/mpd/{tag_cache,state}(2014-6-24追記)Linux Mint 13 MATEの環境だと、削除してしまうと、データベースファイルをtouchしてchownして手動で再作成する必要が生じます。(2015-12-9追記)当時のMint 13 MATE環境でも、ワーニングメッセージは出るものの、手動で再作成の必要はなかったかもしれません。私自身は一応過去どの環境でもtag_cacheを削除してしまっていますので、削除しない場合については推測でしかありません。てことで、面倒なので削除はやめた方がいいです。多分データベースを更新すると文字化けデータは自然に消えるでしょう。


せっかく改良したmpdパッケージが上書きされてしまわないように、できればmpdパッケージをhold(更新禁止)状態に設定しておくべきでしょう。(2015-7-10内容差し替え)

# echo mpd hold | dpkg --set-selections  # 設定
# dpkg --get-selections | grep mpd  # 確認
# echo mpd install | dpkg --set-selections # 解除

lcd4linux の設定

私が使用しているlcd4linux.confの内容はこちらです。
このファイルは次項で説明しているMPDプラグインの私家版(カタカナ表示も対応)の使用を前提としています。逆にMPDプラグインの私家版の方もこのlcd4linux.confの使用を前提としています。両者は不可分です。

 

ダウンロード filelcd4linux.conf

 

plugin_mpd.cをよく見ればわかりますが、このlcd4linux.confを前提としたプログラムとしています。
なのでこの↓2行は(title関数の引数を除いて)絶対に修正しないで下さい。

expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title([num])
expression mpd::elapsedTime().mpd::totalTime()

どうしても修正する場合はplugin_mpd.cをよく理解してからおこなって下さい。ヒント:すべてのデータはmpd::title関数で取得しています。

 

BrightnessとContrast(特にBrightness)は同一のLCD2USBであっても接続するPCが違えば修正が必要になることが多いです。USBポートの電圧はPC毎に微妙に違っていたりするからです。またBrightnessの調整機能は省略しておられる方も多いでしょう。私のLCD2USBの場合はBrightnessが調整可能で、Brightnessを0にするとバックライトがオフになります。

lcd4linux MPD プラグイン(の改造)

本家lcd4linux MPD pluginのページはこちらですが、あまり役立ちません。

修正したソースの内容はこちらです。
ダウンロード fileplugin_mpd.c.gz

 

Ubuntu 10.04(10.10でも同じ)のlcd4linuxパッケージに含まれるMPD pluginは問題大ありでまともに使える状態ではありません。だから標準ではコンパイルされていないのでしょう。私はそれを素直にデバッグせず、動かかない部分を動く(のがわかっている)コードに差替えました。つくりとしてはサンプル的なものなのですが、私自身が使用する書式で出力させる限りは、ずーっと使えてしまうレベルに仕立ててあります。

 

まともに動くように修正するだけでなく、様々な他の修正も加えてあります。

  • カタカナ表示機能の追加(内部的にはUTF-8からSJISへの変換+全角カナ→半角カナ変換の追加)
  • mpd::title関数を、単純にtitleを取得するのではなく、様々な楽曲情報を各々NULL判定をおこないながら繋ぎ合わせ、豊富な情報を取得する関数へと変更
  • mpd::title関数実行時に他の項目の値も一緒に取得するようにしてパフォーマンスを向上。全体に簡易な改造なので逆にこういう工夫が必要になります。
  • configファイル(lcd4.conf)からサーバー名とポート番号を取得する機能を追加
  • webラジオ再生時もしくは再生一時停止時に時刻を表示する機能を追加(webラジオがカレントタイトルの場合はmpdデータベースから取得できる曲のトータル時間が0秒となり、それを表示しても意味がないので、再生時にも現在時刻を表示する)
  • 「1000時間-1秒」まで再生時間を表示するように変更(それ以上の桁は非表示。オリジナルの状態では100分を越す曲を再生するとlcd4linuxが落ちていた)。

lcd4linux MPD プラグインの作成手順

Ubuntu 10.04以降ならわりと簡単にコンパイルできます。Ubuntuでlc4linuxのMPDプラグインをコンパイルする為にはlibmpd-devを手動でインストールする必要があります。(2014-6-24追記)libmpd-devはここで私の紹介する手法を採った場合には必要です。私は今のところlibmpdclient-devの方は使用していません。

 

(2014-6-24追記)現在の私のメイン環境:Linux Mint 13 MATEの場合(多分他の多くの環境でも同じ状況の可能性が高いと思われますが)、lcd4linuxパッケージのビルドに必要なパッケージの一つとして「libgd2-noxpm-dev」が設定されています。これは不具合というべきです。「libgd2-noxpm」は、wineを含め他の多くのパッケージが必要としている「libgd2-xpm」と並立できないからです。lcd4linuxパッケージのビルドに必要なパッケージとしては「libgd2-xpm-dev」が設定されているべきです。現状、下記の「apt-get build-dep lcd4linux」の際に問題が起こりますが、とりあえず適当に対処して下さい。そしてビルドの前にはlcd4linuxパッケージのcontrolファイルをエディタで開き、“libgd2-noxpm-dev”と記述されている箇所を“libgd2-xpm-dev”に書き換えておきましょう。それをおこなった後にlcd4linuxパッケージををビルドしてインストールすれば、次回からはlibgd2-xpmをインストールしたままで、lcd4linuxパッケージのビルドがおこなえます。
(2015-7-10追記)Linux Mint 17.2では上記libgd2-xpmの問題はありません。

 
# apt-get build-dep lcd4linux
# apt-get install libmpd-dev

libmpd-devをインストールし終わった時点で/usr/include/libmpd/libmpd.hというパスが存在するか確かめて下さい。存在しない場合はシンボリックリンクを作成して下さい。
↓こんな感じの作業になると思います。

# cd /usr/include
# ln -s libmpd-*/libmpd  libmpd

libmpd-devのバージョンによりこの通りでない可能性もありますから自分で確認して下さい。
その後は、

$ mkdir hogehoge; cd hogehoge
$ apt-get source lcd4linux
$ cd lcd4linux-*

ここで、このディレクトリにあるplugin_mpd.cを入れ替えます。
ダウンロード fileplugin_mpd.c.gz
入れ替え前のファイルはサンプルレベルのまま何年も更新されていません。しかも入れ替え前も入れ替え後も単一のファイルなので気軽にそっくり入れ替えて下さい。気になる人はdiffを取ってみて下さい。

 

(2014-6-24追記)現在の私のメイン環境:Linux Mint 13 MATEの場合、ここで、configure, plugins.m4の計2ファイルの修正がさらに必要です。修正前はlibmpdclientを使用する仕様になっています。これをlibmpdを使用する設定へと修正します。↓このファイルはその修正をパッチ化したものです。
ダウンロード filelcd4linux_use_libmpd_instead_libmpdclient.patch
configureスクリプトというものはわりと改変頻度が高いので、ソースによってはパッチがあたらない可能性があります。その場合は手動でパッチをあてて下さい。パッチで何をやっているかというと、libmpdclientについて記述されている部分を、Ubuntu 10.04 LTSから持ってきたlibmpdについて記述したもので置き換えているだけです。
(2015-7-10追記)Linux Mint 17.2上でもこのパッチは有効でした。

 

あとは普通です。
私の場合は、

$ dpkg-buildpackage -rfakeroot -uc -nc

上のシンボリックリンクの設定が適切であれば、MPD pluginを含んだlcd4linuxが作成される筈です。
あとは上のディレクトリにできている筈のdebパッケージをインストールして下さい。

# dpkg -i lcd4linux-*.deb

です。

 

せっかく修正したlcd4linuxパッケージが上書きされてしまわないように、できればlcd4linuxパッケージをhold(更新禁止)状態に設定しておくべきでしょう。(2015-7-10内容差し替え)

# echo lcd4linux hold | dpkg --set-selections  # 設定
# dpkg --get-selections | grep lcd4linux  # 確認
# echo lcd4linux install | dpkg --set-selections # 解除

私個人用に時刻表示時にバックライトを消す機能を追加した版

私個人的には、再生一時停止中とインターネットラジオ試聴中はバックライトが必要ないので、バックライトを自動でONOFFする機能を追加しました。

 

パッチファイル(lcd4linux_drv_LCD2USB.c_Backlight_ONOFF.patch)の内容はこちら
ダウンロード filelcd4linux_drv_LCD2USB.c_Backlight_ONOFF.patch
合計で3ファイルの修正が必要なのですが、このパッチはそのうち2ファイル分の修正内容を含んでいます。

 

もう一つの修正対象のファイルはplugin_mpd.cです。このファイルに関しては「lcdbacklight_ONOFF」という変数名が含まれる行(3箇所合計で3行)のコメントアウトを外すだけで対応が完了します。

USB接続の小型キーパッドでMPDを操作(xbindkeys、グローバルホットキー)

やはり操作専用のデバイスがあった方がいいということで、私はUSB接続の小型キーパッド(=USB マイクロマルチコントローラ(MMC))を繋いで使っています。もちろん代わりにマルチメディアキーボードのアプリケーションキーを使ってもいいででしょう。ただその場合はデスクトップ環境のデフォルト機能と干渉する場合がありますから注意が必要です。

 

やっていることは普通のキーボードでのショートカットキー操作と同じです。複雑なショートカットキー操作が1ボタンで済むことがキーパッドを使うメリットです。なので、この項に記述する内容の殆どは「Linuxでのグローバルホットキーの設定」手順の一例としても利用できます。

 

ここでは昔からある「xbindkeys」というコマンドと、MPDをCUIで操作するコマンド「mpc」を用いています。

 

もちろんxbindkeysとmpcをインストールして下さい。
あとは.xbindkeysrcをホームディレクトリに置いてやるだけです。
.xbindkeysrcを見ればわかるように、ネットワーク対応していますので、他のPCからも透過的に操作することができます。

 

設定ファイル(~/.xbindkeysrc)の内容はこちら
ダウンロード file.xbindkeysrc

 

一連のキーの組み合わせは私がWindowsのWinampに対して使用する際の組み合わせと共通です。つまり1台のPCをWindowsとLinuxのマルチブートにした場合にもスムーズに使用することができます。

キー操作設定している動作
Shift + Alt + UpVolume Up
Shift + Alt + DownVolume Down
Shift + Alt + Left10秒巻き戻し
(Winampの場合は巻き戻し)
Shift + Alt + Right10秒進む
(Winampの場合は進む)
Shift + Alt + pPrevious
Shift + Alt + nNext
Shift + Alt + spacePlay/Pause
 

ところで、この項の手法はXが入っていない環境では使えません(裏技もあるにはありますが)。lircならログインしていなくても、Xがインストールされていない環境でも使用することができます。「なら、lircを使えばいいじゃないか」と言われそうですが、私はこの用途にはIRリモコンなんかよりも有線のデバイスが似つかわしいと思います。で、とりあえず実行する予定はないんですが、このMMCを「lirc受信デバイスに改造できればいいなあ」といいう願望を持っています。もちろん本物のlirc受信デバイスではなく、そのふりをするデバイスです。ファームウェアの改造もドライバーの改造も難しくはない筈です(USBクラスを変えて、あとはチョチョイ…程度)。標準カーネルに含まれないドライバーを管理しなくてはならないのがこの手法の運用上の欠点だと思います。

 

ちなみにMMCにはこのような姉妹品があります。

MPD クライアント

MPDクライアントは多種OS用が存在します。

 

iPhone, iPad, iPod, Android, Mac , Windows, Linux, ... その他とても書ききれない多種環境に対応しています。でも既成のWindows用クライアントは意外と少なくて、専用クライアントとしてはgmpcくらいでしょうか。実数としてはMusic Player Minion(Firefoxアドオン,Operaプラグイン,IEツールバー,Yahoo!ウィジェット)が最大かもしれません。Linux用は挙げきれないほどの種類があります。

 

誤解がないように念のため書き添えておきますが、MPDは「Music Player Daemon」なのでクラサバモデルのサーバー側に再生機能があります。必然的にクライアントの構造が簡単になるのでこれほど多種のクライアントが産み出されているのでしょう。

 

サーバ側にこのパッチをあてると、MPDクライアント側は何も変更しなくても、MPDクライアントの画面上でシフトJISのID3タグの内容(アルバム、アーティスト、タイトル)の全てが正しく表示されるようになります

 

ただし、Arioは、標準的なMPDクライアントの仕様から外れた独自仕様として、ID3タグの編集機能を持っています。この機能は内部の仕組み的にもMPDとは全く関係がなく(何しろID3タグ用のライブラリさえ別系統のものを使用しています)、MPDにこのパッチをあてた後も相変わらず文字化けします。Linux上での文字コードがシフトJISのID3タグの編集はEasyTAG等を使用して下さい。

 

私がLinux上で最もよく使っているクライアントはArioです。ちょっとした利点に過ぎないのですが、ArioにはインターネットラジオのURLを登録しておけるインターフェースが用意されいて、他のクライアントより少しだけ便利だと思います。

 

自分好みのMPDクライアントを作りたいなら、Python, PyGTKを使ったクライアント、pympdをベースとすることをお薦めします。

 

※リモートから接続するなら、mpd.conf(MPDデーモン用の設定ファイル)のbind_to_addressをデフォルトのlocalhostから外部から見えるIPアドレスやホスト名に変更しておく必要があります。
(2015-4-18追記)bind_to_addressの行をコメントアウトしておいてもいいみたいですね。

SHOUTcast等のインターネットラジオのURLをMPDに登録し易くするヘルパースクリプト

Ario(mpdクライアント)のインターネットラジオ・ライブラリにSHOUTcast等のplsファイルから取得したURLを追加するちょっとしたお助けスクリプトです。
Arioを起動していない状態で、

$ add-radiourl-to-arioxml.sh hogehoge.pls

みたいな感じで使用します。
複数のplsファイルを一気に処理したい場合は、

$ for i in *.pls;do add-radiourl-to-arioxml.sh $i;done

みたいな感じで使用すればいいでしょう。

 

ダウンロード fileadd-radiourl-to-arioxml.sh

 

実を言うとPerl等を使うと遥かに簡潔に書けますし、汎用性も上がります。

 

(2014-6-24追記)世の中には様々なフォーマットのplsファイルが存在するようで、上記スクリプトは全然万能ではありません。そこで替わりに、既に動作確認のとれたArio用のradios.xmlファイルを提供します。RadioTrayデフォルトの放送局のうち、Arioに追加できるものを抽出したものです。他にNHKのらじるらじるも追加しました。合計69局を含んでいます。残念ながらNHKは曲名を流してくれません。でもNHKを除く殆どの局を選局した場合は曲名がクライアント画面やLCDに表示されます。)
ダウンロード fileradios.xml

/.config/ario/radiosに、そのまま置くか、/usr/share/ario/plugins/radios.xml.defaultとマージした上で同じくradios.xmlという名前で置いたりする等して利用して下さい。この作業はArioを終了した状態でおこなって下さい。

 

(2015-11-21追記)上掲radios.xmlに含まれているNHKらじるらじるのURLですが、2015年9月に変更されました。そして新URLはArioで再生できなくなりました。RadioTrayでは再生できるのでそちらを使って下さい。

備考(Remucoの紹介、MPD以外のプレーヤーをの曲情報をlcd4linux経由で液晶に表示する方法、リモート操作する方法)

実はクラサバ型ではないLinux上の多くのプレーヤーソフトにも、様々、外部から情報を取得したりリモート操作する手段が用意されていたりします。

 

MPRIS(Media Player Remote Interfacing Specification)インターフェースを持ったプレーヤーなら比較的リモート操作するのは簡単(な筈)です。どうもlcd4linuxのMPRISプラグインも一応作られているようですが、現在はダウンロード元が見つかりません。

 

あと、まだご存知なければ、是非知って頂きたいのがRemucoです。RemucoはBluetoothもしくは無線LAN付きの携帯電話をLinux上のメディアプレーヤーソフトのリモコンとして使えるようにするシステムです。ただのリモコンではなく、双方向リモコンなので、携帯電話側にLinux側の曲名やアルバム名を表示して選択することができます。簡単に言えば最近のiPhoneがAppleTVやiTunesを操作できるのと同様な感じでLinuxのメディアプレーヤーソフトをリモート操作できるわけです。

 

  mpd_and_lcd4linux_mpd_plugin_3_s.png  mpd_and_lcd4linux_mpd_plugin_4_s.png
これはRemucoクライアントをエミュレータ上で動作させた際のものです。

 

現時点でもAmarok, Audacious, Rhythmbox, Totem, VLC, Banshee, Exaile, MPD, Quod Libet, Songbird, TVtime, XMMS2の操作に対応しています。

 

Linux上のプレーヤー側の対応の方法としては、プラグイン形式で対応するものとアダプターソフト(プロキシ)形式で対応するものがあります。もちろんプラグイン形式の方がプレーヤーと一体のものとして扱えるので使い勝手がいいです。アダプターソフト形式の場合は、プレーヤーと別にアダプターソフトを起動する必要があります。一部の古いプレーヤーソフトとRemucoクライアントはは完全な双方向通信ができませんが、新しめの(Linux上のメディアプレーヤー)ソフトとRemucoクライアントとはきちんと双方向通信ができるようです。

 

Remucoクライアント(携帯)側は基本的にはJavaアプリ(MIDP2.0クライアント)です。残念ながら日本の携帯電話の場合はBluetoothが付いていても使えないものがあると思います。ただ、簡単な作業でAndroid版を作ることもできます。

 

RemucoクライアントのC言語版もしくはPython版があれば、それを流用してlcd4linux用のプラグインがわりと簡単に作成できると思いますが、残念ながら今のところないようです。もしlcd4linux用のプラグインが作られれば、mpdプラグインより汎用性が高いので私もそっちを主に使うことになると思います。

各ファイルの内容

mpd-0.18.7-cp932.patch(MPDの日本語化(シフトJISタグ対応)パッチ)

説明はこちら
ダウンロード filempd-0.18.7-cp932.patch
[mpd-0.18.7-cp932.patch]

diff -ur orig.mpd-0.18.7/src/tag/TagId3.cxx mod.mpd-0.18.7/src/tag/TagId3.cxx
--- orig.mpd-0.18.7/src/tag/TagId3.cxx	2013-12-12 04:51:53.000000000 +0900
+++ mod.mpd-0.18.7/src/tag/TagId3.cxx	2015-12-09 20:01:41.709309003 +0900
@@ -67,6 +67,125 @@
 	return (id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1) != 0;
 }
+#define USE_CP932
+
+#ifdef USE_CP932
+
+#include <iconv.h>
+
+
+#define UNKNOWN_STR    "UNKNOWN"
+#define MAX_ICONV_BUF 1024
+
+typedef enum {
+  ICONV_OK,
+  ICONV_TRYNEXT,
+  ICONV_FATAL
+} iconv_result;
+
+static iconv_result do_convert(const char* to_ces, const char* from_ces,
+			       char *inbuf,  size_t inbytesleft,
+			       char *outbuf_orig, size_t outbytesleft_orig) {
+  size_t rc;
+  iconv_result ret = ICONV_OK;
+
+  size_t outbytesleft = outbytesleft_orig - 1;
+  char* outbuf = outbuf_orig;
+
+  iconv_t cd  = iconv_open(to_ces, from_ces);
+  if (cd == (iconv_t)-1) {
+    return ICONV_FATAL;
+  }
+  rc = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+  if (rc == (size_t)-1) {
+    if (errno == E2BIG) {
+      ret = ICONV_FATAL;
+    } else {
+      ret = ICONV_TRYNEXT;
+      memset(outbuf_orig, '\0', outbytesleft_orig);
+    }
+  }
+  iconv_close(cd);
+
+  return ret;
+}
+
+static id3_length_t id3_ucs4_length(id3_ucs4_t const *ucs4)
+{
+  id3_ucs4_t const *ptr = ucs4;
+
+  while (*ptr)
+    ++ptr;
+
+  return ptr - ucs4;
+}
+
+static unsigned char* get_utf8_text(const id3_ucs4_t* native_text) {
+  unsigned char* utf8_text = NULL;
+  char * in, * in8, * iconv_buf;
+  iconv_result rc;
+
+  in8 = (char*)id3_ucs4_utf8duplicate(native_text);
+  if (!in8) {
+    goto out;
+  }
+
+  {
+    int ucs4_len = id3_ucs4_length(native_text);
+    int i;
+    for(i = 0 ; i < ucs4_len ; i++){
+      if( native_text[i] > 0xff){
+        return (unsigned char*)in8;
+      }
+    }
+  }
+
+  in = (char*)id3_ucs4_latin1duplicate(native_text);
+  if (!in) {
+    free(in8);
+    goto out;
+  }
+
+  iconv_buf = (char*)calloc(MAX_ICONV_BUF, sizeof(char));
+  if (!iconv_buf) {
+    free(in); free(in8);
+    goto out;
+  }
+
+  /* (1) try utf8 -> cp932 */
+  rc = do_convert("CP932", "UTF-8", in8, strlen(in8), iconv_buf, MAX_ICONV_BUF);
+  if (rc == ICONV_OK) {
+    utf8_text = (unsigned char*)in8;
+    free(iconv_buf);
+  } else if (rc == ICONV_TRYNEXT) {
+    /* (2) try cp932 -> utf8 */
+    rc = do_convert("UTF-8", "CP932", in, strlen(in), iconv_buf, MAX_ICONV_BUF);
+    if (rc == ICONV_OK) {
+      utf8_text = (unsigned char*)iconv_buf;
+    } else if (rc == ICONV_TRYNEXT) {
+      /* (3) try euc-jp -> utf8 */
+      rc = do_convert("UTF-8", "EUC-JP", in, strlen(in), iconv_buf, MAX_ICONV_BUF);
+      if (rc == ICONV_OK) {
+	utf8_text = (unsigned char*)iconv_buf;
+      } else if (rc == ICONV_TRYNEXT) {
+	/* utf-8 including non-japanese char? fallback. */
+	utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
+	free(iconv_buf);
+      }
+    }
+    free(in8);
+  }
+  free(in);
+
+ out:
+  if(!utf8_text) {
+    utf8_text = (unsigned char*)strdup(UNKNOWN_STR);
+  }
+
+  return utf8_text;
+}
+#endif
+
 static id3_utf8_t *
 tag_id3_getstring(const struct id3_frame *frame, unsigned i)
 {
@@ -91,10 +210,10 @@
 {
 	id3_utf8_t *utf8, *utf8_stripped;
 	id3_latin1_t *isostr;
-	const char *encoding;
+//	const char *encoding;
 	/* use encoding field here? */
-	if (is_id3v1 &&
+/*	if (is_id3v1 &&
 	    (encoding = config_get_string(CONF_ID3V1_ENCODING, nullptr)) != nullptr) {
 		isostr = id3_ucs4_latin1duplicate(ucs4);
 		if (G_UNLIKELY(!isostr)) {
@@ -114,12 +233,16 @@
 			return nullptr;
 		}
 		g_free(isostr);
-	} else {
+	} else {*/
+#ifdef USE_CP932
+		utf8 = (id3_utf8_t*)get_utf8_text(ucs4);
+#else
 		utf8 = id3_ucs4_utf8duplicate(ucs4);
+#endif
 		if (G_UNLIKELY(!utf8)) {
 			return nullptr;
 		}
-	}
+//	}
 	utf8_stripped = (id3_utf8_t *)g_strdup(g_strstrip((gchar *)utf8));
 	g_free(utf8);

lcd4linux.conf(lcd4linuxの設定ファイル)

説明はこちら
ダウンロード filelcd4linux.conf
[lcd4linux.conf]

#
#  lcd4linux.conf
#
Variables {
   tick 500
   tack 100
   minute 60000
}
Display LCD2USB {
    Driver 'LCD2USB'
    Size '16x2'
    Brightness 200
    Contrast 210
}
Plugin MPD {
    server '192.168.0.5'
    port 6600
    minUpdateTime 500
}
#
# title(0)は入力されているArtist, Album, Track, Titleを全て表示。
# title(1)はArtistを強制無視。
# title(2)はAlbumを強制無視。
# title(3)はArtist, Albumを強制無視。
# title(4)はTrackを強制無視。
# title(5)はArtist, Trackを強制無視。
# title(6)はAlbum, Trackを強制無視。
# title(7)はTitleだけを表示。
# ※aたとえばtitle(0)であっても、Artist, Album, Trackが入力されていなければ、
# title(7)と同じ表示になる。他の場合も同様。
# ※Titleが入力されていない場合は代わりにファイル名を表示。
#
Widget mpd_title {
    class 'Text'
    expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title(0)
#    expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title(1)
#    expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title(2)
#    expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title(3)
#    expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title(4)
#    expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title(5)
#    expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title(6)
#    expression mpd::SongPos().'/'.mpd::ListLength().' '.mpd::title(7)
    width 16
    align 'M'
    speed 200
    update tick
}
Widget mpd_time {
    class 'Text'
    expression mpd::elapsedTime().mpd::totalTime()
    width 16
    align 'L'
    update tack
}
Layout MPD {
    Row1.Col1 'mpd_title'
    Row2.Col1 'mpd_time'
}
Display 'LCD2USB'
Layout 'MPD'

plugin_mpd.c(私家版MPDプラグインのソース)

説明はこちら
ダウンロード fileplugin_mpd.c.gz
[plugin_mpd.c]※シフトJISで保存しないと動作しません。当サイトのファイルとしては例外的です。基本的にはこの画面からのコピペは避け、gzファイルの方を利用して下さい。

/* This is a modified version
   modified by disklessfun (disklessfun@mail.goo.ne.jp)
*/
/* $Id: plugin_mpd.c 789 2007-04-30 04:48:10Z michael $
 * $URL: https://ssl.bulix.org/svn/lcd4linux/branches/0.10.1/plugin_mpd.c $
 *
 * mpd informations
 *
 * Copyright (C) 2006 Stefan Kuhne <sk-privat@gmx.net>
 * Copyright (C) 2006 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 *
 * This file is part of LCD4Linux.
 *
 * LCD4Linux is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * LCD4Linux is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
/*
 * exported functions:
 *
 * int plugin_init_sample (void)
 *  adds various functions
 *
 */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <iconv.h>
#include <time.h>
#include "debug.h"
#include "plugin.h"
#include <libmpd/libmpd.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif
void strip_file_ext (char *string);
unsigned char getUpperByte(unsigned short data);
unsigned char getLowerByte(unsigned short data);
int isShiftJis1(unsigned char c);
unsigned short zen2Han(unsigned short c);
unsigned short compoundWord(unsigned char u, unsigned char l);
int zen2HanString(const unsigned char *z, unsigned char *h);
void error_callback(MpdObj * mi, int errorid, char *msg, void *userdata)
{
    printf("Error %i: '%s'\n", errorid, msg);
}
static char Section[] = "Plugin:MPD";
static char server[256];
static int port;
static double songpos = 0.0;
static double listlength = 0.0;
static int elapsedtime = 0;
static int totaltime = 0;
static int bef_elapsedtime = 0;
static int bef_totaltime = 0;
static unsigned int same_count = 0;
//extern int lcdbacklight_ONOFF;
static int config_mpd(void)
{
    static int configured = 0;
    char *s;
    if (configured != 0)
        return configured;
    s = cfg_get(Section, "server", "localhost");
	strcpy(server, s);
    free(s);
    cfg_number(Section, "port", 6600, 1, 65536, &port);
    configured = 1;
    return configured;
}
static void title(RESULT * result, RESULT * argv1)
{
	double double_work;
	unsigned int mode;
    char *value = " ";
    char 		*artist;
    char 		*album;
    char 		*track;
    char 		*title;
    MpdObj *mi = NULL;
    mpd_Song	*song = NULL;
	bef_elapsedtime = elapsedtime;
	bef_totaltime = totaltime;
	double_work = R2N(argv1);
	mode = (unsigned int)double_work;
	if (mode > 7)
		mode = 0;
    if (config_mpd() == -1)
        return;
    mi = mpd_new(server, port, NULL);
    mpd_signal_connect_error(mi, (ErrorCallback) error_callback, NULL);
    mpd_set_connection_timeout(mi, 5);
	if (!mpd_connect(mi)) {
		mpd_status_update(mi);
		song = mpd_playlist_get_current_song (mi);
		if (song == NULL)
		{
			songpos = 0.0;
			printf("Error: song = NULL");
		} else {
			if (song->artist)
				artist = strdup(song->artist);
			else {
				artist = strdup("");
			}
			if (song->album)
				album = strdup(song->album);
			else {
				album = strdup("");
			}
			if (song->track)
				track = strdup(song->track);
			else {
				track = strdup("");
			}
			if (song->title)
				title = strdup(song->title);
			else {
				title = basename (song->file);
				strip_file_ext (title);
			}
			songpos = song->pos;
			songpos++;
			#define MAX_BUF 512
			char* buffer = (char*)malloc(MAX_BUF);
			strcpy(buffer, "");
			if (!(mode&1)) {
				if (strcmp(artist, "") != 0) {
					strcat(buffer, artist);
					strcat(buffer, " - ");
				}
			}
			if (!(mode&2)) {
				if (strcmp(album, "") != 0) {
					strcat(buffer, album);
					strcat(buffer, " - ");
				}
			}
			if (!(mode&4)) {
				if (strcmp(track, "") != 0) {
					strcat(buffer, track);
					strcat(buffer, " ");
				}
			}
			strcat(buffer, title);
			char* buffer2 = (char*)malloc(MAX_BUF);
			size_t	in_size = (size_t)(MAX_BUF-1);
			size_t	out_size = (size_t)(MAX_BUF-1);
			char* s_ptr = buffer;
			char* d_ptr = buffer2;
			iconv_t ic = iconv_open("CP932", "UTF-8");
			iconv( ic, &s_ptr, &in_size, &d_ptr, &out_size );
			*d_ptr = '\0';
			iconv_close(ic);
			zen2HanString((unsigned char *)buffer2, (unsigned char *)buffer);
			free(buffer2);
			value = strdup(buffer);
			free(buffer);
		}
		listlength = mpd_playlist_get_playlist_length(mi);
		elapsedtime = mpd_status_get_elapsed_song_time(mi);
		totaltime = mpd_status_get_total_song_time(mi);
		mpd_disconnect(mi);
	} else {
		songpos = 0.0;
		listlength = 0.0;
		elapsedtime = 0;
		totaltime = 0;
	}
	mpd_free(mi);
    /* store result */
    SetResult(&result, R_STRING, value);
}
static void SongPos(RESULT * result)
{
    /* store result */
    SetResult(&result, R_NUMBER, &songpos);
}
#define _mpd_dummy				000
#define _mpd_status_get_elapsed_song_time 	001
#define _mpd_status_get_bitrate			002
#define _mpd_status_get_total_song_time         003
#define _mpd_player_get_repeat                  004
#define _mpd_player_get_random			005
#define _mpd_playlist_get_playlist_length			006
static int mpd_get(int function)
{
    int ret = -1;
    MpdObj *mi = NULL;
    if (config_mpd() == -1)
        return;
    mi = mpd_new(server, port, NULL);
    mpd_signal_connect_error(mi, (ErrorCallback) error_callback, NULL);
    mpd_set_connection_timeout(mi, 5);
    if (!mpd_connect(mi)) {
	switch (function) {
	case _mpd_dummy:
	    ret = 1;
	    break;
//	case _mpd_status_get_elapsed_song_time:
//	    ret = mpd_status_get_elapsed_song_time(mi);
//	    break;
	case _mpd_status_get_bitrate:
	    ret = mpd_status_get_bitrate(mi);
	    break;
//	case _mpd_status_get_total_song_time:
//	    ret = mpd_status_get_total_song_time(mi);
	    break;
	case _mpd_player_get_repeat:
	    ret = mpd_player_get_repeat(mi);
	    break;
	case _mpd_player_get_random:
	    ret = mpd_player_get_random(mi);
	    break;
	}
	mpd_disconnect(mi);
	mpd_free(mi);
    }
    return ret;
}
static void elapsedTime(RESULT * result)
{
    char *value = " ";
    int playTime = elapsedtime;
    if (playTime != -1) {
	char myTime[10];
	memset(myTime, 0, 10);
	int hours   = (int) (playTime / 3600);
	int minutes = (int) (playTime / 60) - 60 * hours;
	int seconds = (int) (playTime % 60);
	if (hours > 0) {
		hours = hours % 1000;
		sprintf(myTime, "%d:%02d:%02d", hours, minutes, seconds);
	} else
		sprintf(myTime, "%d:%02d", minutes, seconds);
	value = strdup(myTime);
    }
    // store result
    SetResult(&result, R_STRING, value);
}
static void elapsedTimeSec(RESULT * result)
{
    int playTime = elapsedtime;
    double d = 0.0;
    if (playTime != -1)
	d = playTime;
    // store result
    SetResult(&result, R_NUMBER, &d);
}
static void totalTime(RESULT * result)
{
    char *value = " ";
    int totTime = totaltime;
    if (totTime != -1) {
	char myTime[11];
	memset(myTime, 0, 11);
	if ((bef_elapsedtime == elapsedtime) &&
		(bef_totaltime == totaltime))
		same_count++;
	else
		same_count = 0;
	if ((totTime != 0) && (same_count <= 10)) {
//		lcdbacklight_ONOFF = 1;
		int hours   = (int) (totTime / 3600);
		int minutes = (int) (totTime / 60) - 60 * hours;
		int seconds = (int) (totTime % 60);
		if (hours > 0) {
			hours = hours % 1000;
			sprintf(myTime, "/%d:%02d:%02d", hours, minutes, seconds);
		} else
			sprintf(myTime, "/%d:%02d", minutes, seconds);
	} else {
//		lcdbacklight_ONOFF = 0;
		time_t timer;
		time(&timer);
		strftime(myTime, 10, " %H:%M:%S", localtime(&timer));
	}
	value = strdup(myTime);
    } else
	value = strdup("ERROR");
    // store result
    SetResult(&result, R_STRING, value);
}
static void totalTimeSec(RESULT * result)
{
    int totTime = totaltime;
    double d = 0.0;
    if (totTime != -1)
	d = totTime;
    // store result
    SetResult(&result, R_NUMBER, &d);
}
static void bitRate(RESULT * result)
{
    char *value = "";
    int rate = mpd_get(_mpd_status_get_bitrate);
    if (rate != -1) {
	char rateStr[4];
	memset(rateStr, 0, 4);
	sprintf(rateStr, "%03d", rate);
	value = strdup(rateStr);
    }
    // store result
    SetResult(&result, R_STRING, value);
}
static void getRepeat(RESULT * result)
{
    char *value = " ";
    int rep = mpd_get(_mpd_player_get_repeat);
    if (rep != -1) {
	if (rep)
	    value = strdup("REP");
	// else value = strdup("   ");
    }
    // store result
    SetResult(&result, R_STRING, value);
}
static void getRandom(RESULT * result)
{
    char *value = " ";
    int ran = mpd_get(_mpd_player_get_random);
    if (ran != -1) {
	if (ran)
	    value = strdup("RND");
	// else value = strdup("   ");
    }
    // store result
    SetResult(&result, R_STRING, value);
}
static void getRepRand(RESULT * result)
{
    char *value = " ";
    int ran = mpd_get(_mpd_player_get_random);
    int rep = mpd_get(_mpd_player_get_repeat);
    if (ran != -1 && rep != -1) {
	char str[9];
	if (rep)
	    sprintf(str, "REP/");
	else
	    sprintf(str, "---/");
	if (ran)
	    sprintf(str, "%sRND", str);
	else
	    sprintf(str, "%s---", str);
	value = strdup(str);
    }
    // store result
    SetResult(&result, R_STRING, value);
}
static void ListLength(RESULT * result)
{
    // store result
    SetResult(&result, R_NUMBER, &listlength);
}
int plugin_init_mpd(void)
{
    AddFunction("mpd::title", 1, title);
    AddFunction("mpd::totalTime", 0, totalTime);
    AddFunction("mpd::totalTimeSec", 0, totalTimeSec);
    AddFunction("mpd::elapsedTime", 0, elapsedTime);
    AddFunction("mpd::elapsedTimeSec", 0, elapsedTimeSec);
    AddFunction("mpd::bitRate", 0, bitRate);
    AddFunction("mpd::getRepeat", 0, getRepeat);
    AddFunction("mpd::getRandom", 0, getRandom);
    AddFunction("mpd::getRepRand", 0, getRepRand);
    AddFunction("mpd::ListLength", 0, ListLength);
    AddFunction("mpd::SongPos", 0, SongPos);
    return 0;
}
void plugin_exit_mpd(void)
{
    /* empty */
}
void strip_file_ext (char *string)
{
	int len;
	int i;
	if (string == NULL || (len=strlen(string))==0 )
	return;
	for (i=len-1; i>0; i--)
	{
		if (string[i] == '.')
		{
			string[i] = '\0';
			break;
		}
	}
	return;
}
unsigned char getUpperByte(unsigned short data)
{
	return (data >> 8) & 0xFF;
}
unsigned char getLowerByte(unsigned short data)
{
	return data & 0xFF;
}
int isShiftJis1(unsigned char c)
{
	return c >= 0x81 && c <= 0x9F || c >= 0xE0 && c <= 0xFC;
}
unsigned short compoundWord(unsigned char u, unsigned char l)
{
	return u * 0x100U + l;
}
unsigned short zen2Han(unsigned short c)
{
	/* 非漢字 */
	if (c < 0x100U) {
		return c;
	}
	/* 空白 */
	if (c == 0x8140U) {
		return ' ';
	}
	/* 英大文字 */
	if (c >= 0x8260U && c <= 0x8279U) {
		return 'A' + c - 0x8260U;
	}
	/* 英小文字 */
	if (c >= 0x8281U && c <= 0x829AU) {
		return 'a' + c - 0x8281U;
	}
	/* 数字 */
	if (c >= 0x824FU && c <= 0x8258U) {
		return'0' + c - 0x824FU;
	}
	{
	int i;
	const char * h =
		"、。,.・:;\?!゙゚^_ー/~|\'\"()[]{}「」+-=<>\\$%#&*@"
		"ァアィイゥウェエォオカキクケコサシスセソタチッツテトナニヌネノハヒフヘホマミムメモャヤュユョヨラリルレロワヲン";
	const char * z=
		"、。,.・:;?!゛゜^_ー/~|’”"
		"()[]{}「」+-=<>¥$%#&*@"
		"ァアィイゥウェエォオカキクケコサシスセソ\タチッツテトナニヌネノ"
		"ハヒフヘホマミムメモャヤュユョヨラリルレロワヲン\0";
	for (i=0;z[i+1];i+=2) {
		if (c == compoundWord(z[i], z[i+1])) {
			return (unsigned char)h[i/2];
		}
	}
	}
	return c;
}
/*
	文字列の全角を半角に変換する
	zen2HanString
	<概要>
	SJISコードの文字列を半角から全角に変換する
	<戻り値>
	int:変換したバイト数
	<引数>
	const unsigned char *z:(in),変換前文字列
	unsigned char *h:(out),変換後文字列
	<補足>
	出力先メモリはコール元で確保する
取得元(中で呼び出される関数も含む)
http://c-program.sublimeblog.net/article/3164177.html
*/
int zen2HanString(const unsigned char *z, unsigned char *h)
{
	int i;
	int ph = 0;	/* 半角位置 */
	size_t l = strlen((char *)z);
	h[0]='\0';
	for (i=0;i<l;i++,ph++,h[ph]='\0') {
		/* 非漢字 */
		if (!isShiftJis1(z[i])) {
			 /* 変換しない */
			h[ph] = z[i];
			continue;
		}
		{
			int j;
			const char *h1 = "カキクケコサシスセソタチツテトハヒフヘホウ";
			const char *z1 =
				"ガギグゲゴザジズゼゾダヂヅデドバビブベボヴ\0";
			const char *h2 = "ハヒフヘホ";
			const char *z2 = "パピプペポ\0";
			for (j=0;z1[j+1];j+=2) {
				if(z[i] == (unsigned char)z1[j] && z[i+1] == (unsigned char)z1[j+1]) {
					h[ph] = (unsigned char)h1[j/2];
					ph++;
					h[ph] = (unsigned char)'゙';
					i++;
					goto cont;
				}
			}
			for (j=0;z2[j+1];j+=2) {
				if (z[i] == (unsigned char)z2[j] && z[i+1] == (unsigned char)z2[j+1]) {
					h[ph] = (unsigned char)h2[j/2];
					ph++;
					h[ph] = (unsigned char)'゚';
					i++;
					goto cont;
				}
			}
		}
		{
			unsigned short c = zen2Han(compoundWord(z[i], z[i+1]));
			i++;
			if (c > 0xFFU) {
				h[ph] = getUpperByte(c);
				ph++;
				h[ph] = getLowerByte(c);
			} else {
				h[ph] = c;
			}
		}
		cont:;
	}
	return ph;
}

&aname: ID too long;

lcd4linux_drv_LCD2USB.c_Backlight_ONOFF.patch(個人用に追加した自動バックライトON・OFF機能のパッチ)

説明はこちら
ダウンロード filelcd4linux_drv_LCD2USB.c_Backlight_ONOFF.patch
[lcd4linux_drv_LCD2USB.c_Backlight_ONOFF.patch]

diff -urN orig.lcd4linux-0.10.1~rc2/drv_LCD2USB.c mod.lcd4linux-0.10.1~rc2/drv_LCD2USB.c
--- orig.lcd4linux-0.10.1~rc2/drv_LCD2USB.c	2007-02-25 21:39:10.000000000 +0900
+++ mod.lcd4linux-0.10.1~rc2/drv_LCD2USB.c	2011-02-09 23:56:55.000000000 +0900
@@ -101,6 +101,10 @@
 extern int usb_debug;
 extern int got_signal;
+extern int lcdbacklight_ONOFF;
+static int static_brightness = 0;
+static int current_lcdbacklight_ONOFF = 1;
+
 /****************************************/
 /***  hardware dependant functions    ***/
 /****************************************/
@@ -332,6 +336,11 @@
     /* buffer is now free again */
     buffer_current_type = -1;
     buffer_current_fill = 0;
+
+	if (current_lcdbacklight_ONOFF != lcdbacklight_ONOFF) {
+	drv_L2U_send(LCD_SET_BRIGHTNESS,lcdbacklight_ONOFF  ? static_brightness : 0, 0);
+	current_lcdbacklight_ONOFF = lcdbacklight_ONOFF;
+	}
 }
 /* enqueue a command into the buffer */
@@ -512,7 +521,8 @@
     }
     if (cfg_number(section, "Brightness", 0, 0, 255, &brightness) > 0) {
-	drv_L2U_brightness(brightness);
+//	drv_L2U_brightness(brightness);
+	static_brightness = drv_L2U_brightness(brightness);
     }
     drv_L2U_clear();		/* clear display */
diff -urN orig.lcd4linux-0.10.1~rc2/lcd4linux.c mod.lcd4linux-0.10.1~rc2/lcd4linux.c
--- orig.lcd4linux-0.10.1~rc2/lcd4linux.c	2007-03-22 15:10:41.000000000 +0900
+++ mod.lcd4linux-0.10.1~rc2/lcd4linux.c	2011-02-09 23:32:41.000000000 +0900
@@ -64,6 +64,7 @@
 int got_signal = 0;
+int lcdbacklight_ONOFF = 1;
 static void usage(void)
 {

.xbindkeysrc(xbindkeysの設定ファイル)

説明はこちら
ダウンロード file.xbindkeysrc
[.xbindkeysrc]

# For the benefit of emacs users: -*- shell-script -*-
###########################
# xbindkeys configuration #
###########################
# Volume Up
"MPD_HOST=192.168.0.5 mpc --no-status volume \+5"
    Shift + Alt + Up
#    m:0x9 + m:0x8 + c:111
# Volume Down
"MPD_HOST=192.168.0.5 mpc --no-status volume \-5"
    Shift + Alt + Down
#    m:0x9 + m:0x8 + c:116
# Seek minus 10seconds
"MPD_HOST=192.168.0.5 mpc --no-status seek \-00:00:10"
    Shift + Alt + Left
#    m:0x9 + m:0x8 + c:113
# Seek plus 10seconds
"MPD_HOST=192.168.0.5 mpc --no-status seek \+00:00:10"
    Shift + Alt + Right
#    m:0x9 + m:0x8 + c:114
# Previous
"MPD_HOST=192.168.0.5 mpc --no-status prev"
    Shift + Alt + p
#    m:0x9 + m:0x8 + c:33
# Next
"MPD_HOST=192.168.0.5 mpc --no-status next"
    Shift + Alt + n
#    m:0x9 + m:0x8 + c:57
# Play/Pause
"MPD_HOST=192.168.0.5 mpc --no-status toggle"
    Shift + Alt + space
#    m:0x9 + m:0x8 + c:65
##################################
# End of xbindkeys configuration #
##################################

add-radiourl-to-arioxml.sh(webラジオ聴取の為のヘルパースクリプト)

説明はこちら
ダウンロード fileadd-radiourl-to-arioxml.sh

#!/bin/bash -e
# Ario(mpdクライアント)のインターネットラジオ・ライブラリに
# SHOUTcast等のplsファイルから取得したURLを追加する。
#
[ $# -lt 1 ] && echo "$0 playlist" && exit 1
title="`grep Title "${1}"|cut -d")" -f2-|cut -b2-|head -1`"
title=$(echo "${title}"|sed -e 's/&/&amp;/'g)
title=$(echo "${title}"|sed -e 's/>/&gt;/'g)
title=$(echo "${title}"|sed -e 's/</&lt;/'g)
title=$(echo "${title}"|sed -e 's/&#224;/&#xE0;/'g)
title=$(echo "${title}"|sed -e 's/&#236;/&#xEC;/'g)
title=$(echo "${title}"|sed -e 's/&#249;/&#xF9;/'g)
title=$(echo "${title}"|sed -e 's/&#232;/&#xE8;/'g)
title=$(echo "${title}"|sed -e 's/&#242;/&#xF2;/'g)
title=$(echo "${title}"|sed -e 's/&#228;/&#xE4;/'g)
title=$(echo "${title}"|sed -e 's/&#239;/&#xEF;/'g)
title=$(echo "${title}"|sed -e 's/&#252;/&#xFC;/'g)
title=$(echo "${title}"|sed -e 's/&#235;/&#xEB;/'g)
title=$(echo "${title}"|sed -e 's/&#246;/&#xF6;/'g)
title=$(echo "${title}"|sed -e 's/&#8364;/&#x20AC;/'g)
url="`grep http "${1}"|head -1|cut -d"=" -f2`"
WEBRADIOXML=$(echo ~/.config/ario/radios/radios.xml)
WEBRADIODIR=${WEBRADIOXML%/*}  # 最後の/より前の文字列を取り出す
if !(test -e ${WEBRADIOXML}) then
mkdir -p ${WEBRADIODIR}
cp -p /usr/share/ario/plugins/radios.xml.default ${WEBRADIOXML}
fi
unset TEMPFILE
exitproc()
{
rm -rf ${TEMPFILE}
}
trap '
exitproc
exit 1
' 2 15
TEMPFILE=$(mktemp)
echo "<?xml version=\"1.0\" standalone=\"no\"?>" >> ${TEMPFILE}
echo "<ario-radios>"                             >> ${TEMPFILE}
grep "<radio url=" ${WEBRADIOXML}|while read -r i
do
echo "  ${i}"             >> ${TEMPFILE}
done
echo -n "  <radio url=\"" >> ${TEMPFILE}
echo -n "${url}"          >> ${TEMPFILE}
echo -n "\">"             >> ${TEMPFILE}
echo -n "${title}"        >> ${TEMPFILE}
echo    "</radio>"        >> ${TEMPFILE}
echo  "</ario-radios>"    >> ${TEMPFILE}
cat ${TEMPFILE} > ${WEBRADIOXML}
exitproc
 

ご要望、ご意見、質問を下のフォームにどうぞ
(でもここより、掲示板書き込みフォームのページに書いて頂いた方が気づき易いと思います。)