REGZA の VGA 入力で「対応していない信号です」を回避 (Ubuntu Server 14.04)

HP Microserver を調子よく使っていたところ、ある日急に音楽サーバー(mpd)動画サーバー(Plex)ともに接続できなくなってしまいました。 ssh でも接続できないのでサーバーのログ等も確認できない状態です。 家には普通のパソコンモニターが無く、ssh で接続できないと何も確認できず困ってしまいました。

幸い、テレビ(REGZA 32C3500)には VGA 入力があったので接続してみましたが、起動の途中で「対応していない信号です」という表示が出て表示が消えてしまいます。

解決方法

grub のメニュー上で e キーを押し、カーネルオプション "nomodeset" を (linux で始まる行の末尾に) 追加して Ctrl+x で起動する。 これで、「対応していない信号です」とはならずにログインするまで表示が消えずに済みました。

結局、サーバーに接続できなかった理由は無線のアクセスポイント(がハブを兼ねている)か、ADSLルーターのどちらかの問題だったようです。 両方の電源を入れなおしたところ無事つながるようになりました。

めったに使わないパソコンモニターを買わずに済んで助かりました。

mp3 ファイルの文字化けを修正

iTunes に登録されていたファイルを mpd サーバーにコピーしてみたところ、mp3 ファイルで日本語の曲名やアルバム名などで文字化けが発生することに気づきました。どうやら mp3 のタグの文字コードが Shift-JIS になっているようで、iTunes では問題なく表示されるものの mpd では NG のようです。iTunes でも mpd でも文字化け無く表示できるよう、文字コードを変換することにしました。 Python 用の eyeD3 という mp3 のタグを読み書きできるモジュールがあるようなので、

あらびき日記

の記事を参考に変換スクリプトを作ってみることにしました。以前作成した Mac OSX 10.9, Python 2.7, virtualenv 環境で開発します。

eyeD3 モジュールのインストール

$ pip install eyeD3

でインストールできるかと思ったら、

Downloading/unpacking eyeD3
  Could not find any downloads that satisfy the requirement eyeD3
  Some externally hosted files were ignored (use --allow-external eyeD3 to allow).
Cleaning up...
No distributions at all found for eyeD3
Storing debug log for failure in /Users/iwamoto/.pip/pip.log

と、エラーが出てしまいました。なぜエラーが出るかはよくわかりませんが

$ pip install --allow-external eyed3 --allow-unverified eyed3 eyed3

とすることで、うまくいきました。

chardet モジュールのインストール

文字コードの自動判定機能を使いたいので chardet モジュールをインストールします。

$ pip install chardet

こちらはすんなりインストール出来ました。

プログラム仕様

  • 指定フォルダー以下の拡張子 .mp3 を処理対象とする。それ以外のファイルに対しては何もしない。
  • 保存する際、ID3タグのバージョンは ID3v2.3 にする。保存の際にエラーが出たら(ID3v2.3に無いタグを使っている可能性があるので)ID3v2.4 で保存する。文字コードUTF-16 とする。
  • 文字列が格納されているタグはすべて文字コード変換対象とする。変換ルールは以下の通り。
  • 文字コード変換済みのタグをファイルに保存する。

※ の部分では正しく変換できるかどうかわからないので、あらかじめファイル名とエンコーディングの対応関係を指定してあった場合は、cp932 ではなく指定されたエンコーディングを使うこともできるようにする。

プログラム

bitbucket に公開しておきました。

注意: このプログラムを -x オプション付きで実行すると MP3 ファイルに埋め込んであるジャケット画像が消えてしまいます。消えて良い場合だけ実行してください。

まず、

$ python modid3.py -v .

とすると、カレントディレクトリ以下の全ての MP3 ファイルを検索し、対象となるファイルと変換後の文字列を画面に表示します。文字化けがないか(目視で!)確認します。文字化けがなければ

$ python modid3.py -v -x .

と -x オプション付きで実行すると実際に文字コードが修正されます。なお、-i オプション付きで実行すると eyeD3 モジュールが出す警告メッセージを表示しないようにします。もし、最初の

$ python modid3.py -v .

の実行で文字化けがあった場合は、文字化けが発生したファイルのパス名(の一部)と正しいエンコーディングとの対応関係を PREFERRED_ENCODINGS リストに追加するとそのエンコーディングを使って文字コードを変換します。

<続> 音楽サーバー(mpd) から AirPlay スピーカーを鳴らす

前回の記事で、当初考えていたことは実現できました。その他に追加で設定した内容を記録しておきます。

samba 共有の作成

mpd 用の音楽ファイルを格納するフォルダーは /var/lib/mpd/music ですが、このフォルダーに他のマシンからファイルをコピーできると何かと便利なので samba 共有を作っておきます。 大きめのパーティションを /mnt/pool にマウントしているので、/mnt/pool/itunes を作成してここを samba 共有にします。

$ sudo apt-get install samba
$ sudo mkdir /mnt/pool/itunes
$ sudo chown mpd:audio /mnt/pool/itunes

/etc/samba/smb.conf を編集し、末尾に以下の内容を追加します。

[itunes]
   comment = iTunes Media
   path = /mnt/pool/itunes
   browsable = yes
   read only = no
   guest ok = yes
   force user = mpd

さらに、/var/lib/mpd に /mnt/pool/itunes へのシンボリックリンクを作成します。

$ sudo ln -s /mnt/pool/itunes /var/lib/mpd/music

これで、他のマシンから "itunes" として見える共有フォルダーに音楽ファイルをコピーして mpd に認識させることができるようになりました。

アルバムジャケットの表示

MPoD では、アルバムジャケットを表示する機能があります。私は主に AAC 形式(.m4a)で音楽ファイルを作っており、アルバムジャケットをファイルに埋め込んでいるので、これを表示したいと思いました。みすず工房 というページでそのものずばりのソフトウェアが公開されていたので、これを利用させてもらうことにしました。 Ruby アプリケーションなので、Ruby および必要なモジュールをインストールします。

$ sudo apt-get install ruby
$ sudo gem install ruby-audioinfo

次に、mpodjacket をダウンロードし、/usr/local/bin にインストールします。

$ curl -O -L http://mimizukobo.sakura.ne.jp/cgi-bin/downlog.cgi?data/mpodjacket.tgz
$ gunzip mpodjacket.tgz
$ tar xvf mpodjacket.tar
$ sudo cp mpodjacket.rb /usr/local/bin

マシン起動時に自動起動させるため、/etc/rc.local に("exit 0" の行より前に)以下を追加します。一応、mpd ユーザーで実行するようにしてみました。

sudo -u mpd /usr/local/bin/mpodjacket.rb -r /var/lib/mpd -m /music -p 8888 >/dev/null 2>&1 &

マシンを再起動して動作を確認します。

sudo shutdown -r now

MPoD (iPhone の mpd クライアント)で、"Connections" メニュー内の "Advanced" ボタンを押し、"URL" に

http://{hostname}:8888/music

と入力します。うまくアルバムジャケットが表示されました。

音楽サーバー(mpd) から AirPlay スピーカーを鳴らす

Ubuntu Server 14.04 をインストールして動画サーバーにしている HP Proliant MicroServer N54L に音楽サーバーの機能を追加してみようと思いました。やりたいこと(条件)は、

  • サーバーはよくON/OFFするので起動/シャットダウンは速くしたい。そのため、X はインストールしたくない
  • 同じ理由で、ログオンしない状態で音楽サーバーとして機能するようにしたい
  • 家にある 2 台の AirPlay デバイス(AirMac Express と Pioneer XW-SMA3)にストリーミングして再生したい
  • 手持ちの iPhone から曲の選択等、コントロールしたい
  • 再生した曲は Last.fm に Scrobble したい
  • 曲は OSX 上の iTunes にためてある。この曲データを(rsync等で)フォルダーごとサーバーにコピーするだけで再生対象になるようにしたい

という感じです。色々調べた結果、以下のソフトウェアで実現できそうだということがわかりました。

  • mpd
  • mpdscribble
  • PulseAudio と、そのプラグイン raop モジュール
  • MPoD (iOS アプリケーション)

自分なりに理解したのは、

  • mpd は iTunes みたいなもの(ただし、GUIは無いサーバープログラム)。音楽サーバーの中心となるプログラム。
  • MPoD は mpd のクライアントである。
  • mpd で再生した場合、音の出力先には PulseAudio を選択できる
  • PulseAudio には色々なモジュールを組み込めるが、raop モジュールを組み込むと、AirPlay デバイスにストリーミングできる
  • mpdscribble もサーバープログラム。mpd で再生している曲を調べ、Last.fm に Scrobble してくれる

しかし、慣れていないこともあって色々な所でつまづいてしまい、構築に結構時間がかかってしまいました。特につまづいた箇所は、以下の2点でした。

raop モジュール

Ubuntu Server 14.04 では PulseAudio と raop モジュールは両方とも apt-get で簡単にインストールできます。ところが、再生してみるとブチブチ音が途切れてまともに再生できません。raop2 モジュールというのがあるようなので、それを試してみたところうまくいきました。

PulseAudio の System Mode

PulseAudio はログオンしたユーザーの権限で起動させるのが基本のようで、ウェブ上の解説記事もそれに沿ったものが多く見つかります。上に書いたようにログオンしない状態で動作させたいので迷ったのですが、System Mode という動作方法を試してみるとうまくいきました。System Mode は、

WhatIsWrongWithSystemWide

に書かれているようにセキュリティ上問題があったり、一部の機能が使えなかったりするようですが他に良い方法も思いつかなかったのでとりあえず良しとします。

手順

せっかくうまくいったので手順をまとめておきます。

PulseAudio (raop2) のインストール

開発元のサイト Pulseaudio-raop2 の手順通りにビルドします。

$ sudo apt-get update
$ sudo apt-get install build-essential paprefs git pulseaudio-module-raop intltool
$ sudo apt-get build-dep pulseaudio
$ git clone https://github.com/hfujita/pulseaudio-raop2.git
$ cd pulseaudio-raop2
$ ./autogen.sh
$ CFLAGS="-ggdb3 -O0" LDFLAGS="-ggdb3" ./configure
$ make

この後リンク先の手順では動作確認をするのですが、ここではそのままインストールしてしまいます。

$ sudo make install

/usr/local 以下にインストールされます。

$ pulseaudio --start

と実行してみると、

pulseaudio: error while loading shared libraries: libpulsecore-5.99.so: cannot open shared object file: No such file or directory

というエラーが出たので、

$ sudo ldconfig

を実行して共有ライブラリの依存関係情報を更新してやります。次に、/usr/local/etc/pulse/default.pa と、/usr/local/etc/pulse/system.pa の末尾に以下の行を追加します。

load-module module-raop-discover

default.pa は通常のモードで起動した時の設定ファイル、system.pa は System Mode で起動した時の設定ファイルとのことです。一度通常のモードで起動させ、AirPlay デバイスに接続できるか確認するとともに AirPlay デバイスの名前を確認します。もちろんこの時点で AirPlay デバイスは電源を入れておく必要があります。

$ pulseaudio --start
$ pacmd list-sinks | grep name:
        name: <alsa_output.pci-0000_00_1f.4.analog-stereo>
        name: <raop_output.Base-Station-xxxxxx.local>
        name: <raop_output.XW-SMA3-xxxxxx.local>

raop_output という文字列が含まれる行が AirPlay デバイスを表します。ここでは2台(AirMac Express と Pioneer XW-SMA3)見つかっています。<> で囲まれた文字列は後で mpd の設定に使うので記録しておきます。

次に、今ビルドした(/usr/local/bin にある) pulseaudio を System Mode で動作させるために /etc/init/pulseaudio.conf を以下のように編集します。

start on runlevel [2345]         <---- コメントアウトを解除

exec /usr/local/bin/pulseaudio --system --daemonize --high-priority --log-target=syslog --disallow-exit --disallow-module-loading=$DISALLOW_MODULE_LOADING $PULSEAUDIO_ARGS    <--- /usr/bin/pulseaudio を /usr/local/bin/pulseaudio に修正

また、System Mode では autospawn 機能(PulseAudio のクライアントプログラムが必要に応じて PulseAudio を起動させる機能)は不要なので無効にするため、/usr/local/etc/pulse/client.conf に以下の行を追加します。

autospawn = no

いったんここで再起動します。

$ sudo shutdown -r now

起動後、動作しているか確認します。

$ ps aux | grep pulse

残念ながら起動していませんでした。/var/log/syslog を確認すると

Feb 28 13:08:37 pubuntu pulseaudio[1158]: [pulseaudio] core-util.c: Failed to create secure directory (/usr/local/var/lib/pulse): Permission denied

というエラーが出ていました。

$ ls -l /usr/local/var
合計 8
drwx------ 3 root root 4096  2月 28 13:08 lib
drwxr-xr-x 3 root root 4096  2月 28 13:08 run

ということで、/usr/local/var/lib には root 以外はアクセスできないようになっていました。正しい対応であるかはわかりませんが

$ sudo chmod 755 /usr/local/var/lib

と root 以外でもアクセス可能にしました。もう一度再起動して確認してみます。

$ ps aux | grep pulse
pulse     1071  0.0  0.1 200944  3768 ?        S<l  17:23   0:00 /usr/local/bin/pulseaudio --system --daemonize --high-priority --log-target=syslog --disallow-exit --disallow-module-loading=1

今度はうまく行ったようです。

mpd のインストール
$ sudo apt-get install mpd

/etc/mpd.conf を編集し、一部の設定を変更します。

bind_to_address         "0.0.0.0"   <--- 任意のネットワークインターフェースでの接続を有効にします

audio_output {
        type            "pulse"
        name            "AirMac Express"
        sink            "raop_output.Base-Station-xxxxxx.local"
}

audio_output {
        type            "pulse"
        name            "Pioneer XW-SMA3"
        sink            "raop_output.XW-SMA3-xxxxxx.local"
}

/var/lib/mpd/music に何か音楽ファイルをコピーして mpd のデータベースをアップデートし、mpd クライアントである ncmpcpp で再生してみます。

$ sudo apt-get install mpc ncmpcpp
$ sudo cp Sally.m4a /var/lib/mpd/music
$ mpc update
$ ncmpcpp

Sally.m4a を再生してみましたが、すぐに Pause 状態になってしまいうまく行きません。/var/log/mpd/mpd.log を調べました。

Feb 28 18:47 : pulse_output: Failed to open "AirMac Express" [pulse]: failed to connect: Access denied

PulseAudio からアクセスが拒否されているようです。PulseAudio - Music Player Daemon Community Wiki を参考に以下を実行しました。

$ sudo usermod -aG pulse,pulse-access mpd

もう一度 ncmpcpp で再生しましたがやはり再生できません。/var/log/mpd/mpd.log のエラーメッセージは次の通り。

Feb 28 19:03 : pulse_output: "AirMac Express" [pulse] failed to play: failed to connect the stream: No such entity

"entity" というのは、音声の出力先(mpd.conf で、audio_output として定義したもの)を指していると思います。おそらく PulseAudio の raop モジュールが正しくロードできていないのではないかと推測しました。で、もしかしてと思い /etc/init/pulseaudio.conf を以下のように編集しました。

env DISALLOW_MODULE_LOADING=0      <--- 1 を 0 に変更

この状態で OS を再起動したところ、ncmpcpp で再生に成功しました! なお、PulseAudio が AirPlay デバイスと接続できているかは以下のコマンドで確認できます。

$ sudo -u pulse pactl list short | grep module-raop-sink

これで "raop_output.Base-Station-xxxxxx.local" のような文字列が出力されれば OK です。なお、PulseAudio を System Mode で動作させているときは、上記の通り pulse ユーザーで pactl コマンドを実行する必要があります。また、pactl と似たような機能を持つ(違いがよくわからない) pacmd というコマンドもありますが、こちらは pulse ユーザーでも実行できませんでした。

MPoD のインストール

普通に App Store からインストールします。"Connections" メニューから今設定した mpd サーバーに接続します。"DISCOVERED PLAYERS" に表示されたものを選ぶか、"Add player manually" を選択して IP アドレスを入力します。接続後、曲が再生できるか確認します。

mpdscribble のインストール
sudo apt-get install mpdscribble

自動起動させるために /etc/default/mpdscribble を編集。

MPD_SYSTEMWIDE=1       <---- 0 を 1 に変更

Last.fm への接続情報を /etc/mpdscribble.conf に設定。

[last.fm]
url = http://post.audioscrobbler.com/
username = foo     <--- ユーザー名を設定
password = bar     <--- パスワードを設定

これでようやく最初に書いた条件がクリア出来ました。

参考にしたサイト

raspbian - Redirect audio to another AirPlay device - Raspberry Pi Stack Exchange

MPD INSTALL USER SERVICE UBUNTU - Gnome Music Player Client

PulseAudio - Music Player Daemon Community Wiki

Windows のスタートスクリーンに自動回転オンオフのアイコンを作る

Windows タブレットを使っていると、画面の自動回転機能の有効/無効を切り替えたくなることがあります。標準機能では

  • チャームを出す
  • 「設定」を押す
  • 「ディスプレイ」を押す
  • 自動回転オンオフのアイコンを押す

でできるのですが、4回操作が必要なことと、7インチタブレットではアイコンが小さくて押しにくいことからスタートスクリーンに自動回転の有効/無効を切り替えるアイコンを置けないか考えてみました。

方法

調べてみたところ、Windows キーを押しながら o キーを押すことで自動回転機能の有効/無効の切り替えができることがわかりました。タブレットにはキーボードがないし、スクリーンキーボードを出すのは手間なので、AutoHotkeyスクリプトで Win+o キーのキーコードを送ってみることにしました。

Send #o
Send {LWin}
  • デスクトップ等に "C:\Program Files\AutoHotkey\AutoHotkey.exe" へのショートカットを作成する
  • ショートカットを右クリック(長押し)し、プロパティを開く
  • 「リンク先」の末尾に C:\etc\autorotation.ahk を追記して OK をクリックする
  • ショートカットを右クリック(長押し)し、「スタートにピン止め」をクリックする

これで、スタートスクリーンに自動回転機能の有効/無効を切り替えるアイコンができます。現在、回転が有効か無効かがわからないのが難点ですが(アイコンをクリックすると画面左上に切り替え後の状態は表示される)、個人的にはずいぶん便利になりました。

Linux マシンをリモートから電源オンオフするアプリ

HP の小型サーバー "HP Proliant MicroServer N54L" が激安だったので買って Ubuntu ServerPlex Media Server をインストールして動画サーバーにしました。 消費電力は少なめですが、やはり電源入れっぱなしは電気がもったいないので動画を見ない時は電源を切っています。タブレット(Windows 8.1)でこのサーバーに入れた動画を見る時に電源を入れたり見終わった時に電源を切りためにサーバーの近くまで行くのが面倒なのでリモートで電源オンオフするアプリを作ってみました。

開発言語

お手軽なのとデスクトップパソコン(iMac)からも使いたいので Python で作ることにしました。また、GUI もつけたいと思ったのですが凝った UI は不要なので標準で入っている Tkinter を使います。

電源オン

HP Proliant MicroServer は Wake on LAN に対応しているので同一 LAN 内であれば他のパソコンから電源オンできそうです。emptypage.jp の方が wol.py を公開してくださっているのでそのまま使わせてもらうことにしました。

電源オフ

ssh でリモートログインして shutdown コマンドを実行するという方法をとることにしました。Paramiko という便利なモジュールがあるのでこれを使います。

ステータス表示

サーバーの電源が今オンなのかオフなのかはわかったほうが良いので定期的に ping を打って応答を確認するようにしました。Mac OSX では ping コマンドの終了コードが 0 であることを確認するだけで良いのですが、Windows の場合はサーバーの電源がオフで ping に応答しない場合でも終了コードが 0 になる場合がありました。そこで、Windows の場合は ping の出力に "unreachable" や "Received = 0" という文字列が含まれていたら電源オフ、含まれていなければ電源オンと判断することにしました。

Windowsping への対応

日本語 Windows で実行した場合 ping の応答も日本語で帰ってくるので、それぞれ "到達できません", "受信 = 0" で判断する必要がありました。なので、日本語/英語以外のロケールで実行すると正しく動作しません。英語モードに切り替えて ping を実行できればよいのですがやり方がわかりませんでした...。*1 Windows では ping コマンドの実行ではなく、Windows API (ICMPSendEcho) を使って ICMP パケットを投げたほうが良いのかもしれません。

ping の非同期実行

pingPython の subprocess モジュールで実行させました。subprocess.call() で実行するのが簡単なのですが、実行が完了するまで待つのでサーバーが起動しておらず pingタイムアウトになる場合はタイムアウトになるまで UI が応答しなくなってしまいます。マルチスレッドにしても良いのでしょうが、なんだか大袈裟さので proc = subprocess.Popen() で ping を実行し、proc.poll() で終了するまでポーリングすることにしました。

py2exe

実際に動かす Windows タブレットPython や Paramiko モジュールをインストールしなくても動作するよう py2exe を使って EXE 化することにしました。

というわけで

bitbucketソースコードWindows 用バイナリーを置いておきました。以下のコマンドラインオプションをセットする必要があります。

-h オンオフしたいマシンのIPアドレス
-m オンオフしたいマシンのMACアドレス
-u マシンにログインするためのユーザー名(sudo で shutdown コマンドを実行できる権限を持っている必要あり)
-p -u で指定するユーザーのパスワード
-g GUI モードを指定

-g の代わりに -w を指定すると GUI なしにマシン起動を実行します。同じく -s を指定するとマシンをシャットダウンします。

f:id:loopdeloop:20150201215313p:plain

f:id:loopdeloop:20150201215321p:plain

TODO

エラー処理をまともにする。

*1:cmd.exe で "chcp 437 & ping" を実行したところ、普通に Python インタプリタ経由では OK なのに、py2exe で EXE 化したら NG でした。

screen 上で vim の 256 色対応のカラースキームを適用

OSX の Terminal.app (上の screen) 上で vim を使って Python のプログラムを書くことにした。 Terminal.app の環境設定で背景が黒の "Pro" というプロファイルを使うことにしたが、やはりシンタックスハイライトが効いてほしい。以下メモしておく。

NeoBundle

vim 上に色々インストールするには、最近では NeoBundle という仕組みがよく使われているようだ。とりあえずインストールしておく。(インストール方法省略)

シンタックスハイライトを有効にする

~/.vimrc:

syntax on

カラースキームをインストール

[vim] 黒背景好きの僕の心を揺さぶるカラースキーム「hybrid」 | ここぽんのーと

で紹介されていたカラースキームをとりあえず全部インストール。

~/.vimrc:

NeoBundle 'nanotech/jellybeans.vim'
NeoBundle 'w0ng/vim-hybrid'
NeoBundle 'vim-scripts/twilight'
NeoBundle 'jonathanfilip/vim-lucius'
NeoBundle 'jpo/vim-railscasts-theme'
NeoBundle 'altercation/vim-colors-solarized'
NeoBundle 'vim-scripts/Wombat'
NeoBundle 'tomasr/molokai'
NeoBundle 'vim-scripts/rdark'

試してみる

vim を起動して

:colorscheme jellybeans

とかやってみるが、どうも色が紹介画像と違う。どうやらターミナルエミュレータ(今回の場合 screen)が 256 色対応であると vim に教えてやる必要があるらしい。

screen の上で 256色の vim を使う - Hack like a rolling stone

にならって、以下の設定を ~/.vimrc に加えた。

" Enable 256 colors FORCELY on screen
if $TERM == 'screen'
    set t_Co=256
endif
colorscheme jellybeans

これで、jellybeans というカラースキームで立ち上がるようになった。ところでシンタックスハイライトとかカラースキームって日本語で何て言うんだろうか。

追記

...次の日にやってみたら 256 色が出なくなっていた。OSX 付属の screen は 256 対応のコンパイルオプション付きでビルドされていないようだ。うまく行ったのは気のせい?? とりあえず screen を

MacOSX - Mac OS X の NFD 問題での対策諸々 - Qiita

を参考にビルドして使うことにした。