FunnelのライブラリでGAINER miniを試そうとしたら、バグで動きやがらねぇので修正して動かす。

このエントリをはてなブックマークに追加このエントリをはてなブックマークに追加このエントリをdel.icio.usに追加このエントリをLivedoor Clipに追加このエントリをLivedoor Clipに追加このエントリをYahoo!ブックマークに追加このエントリをFC2ブックマークに追加このエントリをNifty Clipに追加このエントリをPOOKMARK. Airlinesに追加このエントリをBuzzurl(バザール)に追加このエントリをBuzzurl(バザール)に追加このエントリをChoixに追加このエントリをnewsingに追加このエントリをkwoutに追加
2008年12月3日 水曜日1:26:01

前回のエントリでGainer miniでマトリクスLEDを試したが、
その後調べてみるとFunnelなるハードウェア用のライブラリでも、Gainerを動かせるらしい。
しかも、MatrixLEDなるクラスまであり、Bitmapを受け取って
マトリクスLEDの光を操作することが出来るようだ。
これは是非試さなくてはと思い、早速Funnelの最新β、009b1を入手。
ActionScript3.0用には、ソースをSubversionのリポジトリから手に入れた。
さあ試すぞ!

・・・

その結果(swfが出してきたエラー)

Error #2044: ハンドルされていない configurationError : text=Can't find such a configuration

動かない。
どうも、モード(今回はモード7)を認識していないようだ。
折角ソースを手に入れたので、色々と調べてみる。
で、2日ほどかけて調査した結果、Funnel Serverの方にエラーがあると判明。
原因はCommandPortClient.javaにあった。
もうどうしようもないくらい単純なバグで、判明した瞬間涙出てきた。
あと、こんな低レベルなバグを残してしまうFunnelに対して不安になった。

流石にIssueしといた
アカウントは、太郎日記’79J用のしかないのでそれで。

バグの原因

まず、何故configurationErrorになるかと言うと、
Gainerの8つのモードのどれにも該当しないような、
不正な/configure命令をFlashからFunnel Serverに送信したから。
正確には、Flash側の送信は正しかったが、Funnel Server側の受信機能が壊れていたため。
プロトコルでは、まず先頭4バイトがパケット長なのだが、
そのパケット長の計算がこのようになっている。

int packetSize = ((buffer[processedSize + 0] <<24) & 0xFF)
        + ((buffer[processedSize + 1] <<16) & 0xFF)
        + ((buffer[processedSize + 2] <<8) & 0xFF)
        + (buffer[processedSize + 3] & 0xFF);

これがダメだ。
よく見ると分かるが、最後の(buffer[processedSize + 3] & 0xFF)以外は
全部0になる。
例えば、buffer[processedSize + 0]の値が255(0xFF)だとすると、
(buffer[processedSize + 0] << 24)は0xFF000000になる。
で、0xFF000000 & 0xFFなので、答えは0になる。
この調子で上3行が全滅するので、最後の行しか残らない。
するとどうなるかと言うと、長さが256以上のパケットを受け取ろうとしても取れない。
パケット長を256で割った余りの分だけ、パケットを取ってしまう(つまり途中)
例えば、モード7ですよと言う宣言の場合、
正しくはこうなる(最後の括弧内がパケット長)。

packet:[47,99,111,110,102,105,103,117,114,101,0,0,44,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,(340)]

が、現在のFunnel Serverはこうなる。

packet:[47,99,111,110,102,105,103,117,114,101,0,0,44,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,0,0,0,0,0,0,(84)]

正しい長さ340=256+84で、見事間違った長さと一致だ。

なお、大量に出てくる105とは、「i」のASCIIコードで、int型(4byte)を表す。
最初に型の列挙が出てきて、その後実際の値だ。
今回の場合、「0,0,0,2」で要するに2だ。
現状版だと、値の部分がゴッソリ無くなって、全部0扱いになる。
2(アナログ出力を表す値)が64個並ぶのがモード7である。
オール0は無い。よって、未知のモード(configuration)だと言われてエラーが出るわけだ。

誰だこんな改悪入れやがった奴はー!

などと怒りに震えながら、CommandPortClient.javaのログを見ていき、遂に変更点を発見。
これだ。

Modified to handle a packet size correctly
Since byte in Java is signed, we have to do '& 0xFF' to convert from signed byte
(but actually unsigned byte) to int

この、「パケット長を正しく取るための変更」と言う一文が、
空しく光るわ。

修正するには?

と言う事で、以下のように変更してみる。

int packetSize = ((buffer[processedSize + 0]&0xFF) <<24)
        + ((buffer[processedSize + 1]&0xFF) <<16)
        + ((buffer[processedSize + 2]&0xFF) <<8)
        + (buffer[processedSize + 3] & 0xFF);

多分、これでいいと思う。
MatrixLEDを動かしてみたら、ちゃんと動いたし。

2日もエラーを探し続けたので、若干怒りのこもったエントリーになってしまった。
と言うか、今まで誰も気付かなかったのか?

トラックバック URL :

コメントをどうぞ

HTML convert time: 1.394 sec.