前回のエントリで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);
- [/java]
- これがダメだ。
- よく見ると分かるが、最後の<code>(buffer[processedSize + 3] & 0xFF)</code>以外は
- 全部0になる。
- 例えば、<code>buffer[processedSize + 0]</code>の値が255(0xFF)だとすると、
- (buffer[processedSize + 0] << 24)は0xFF000000になる。
- で、<code>0xFF000000 & 0xFF</code>なので、答えは0になる。
- この調子で上3行が全滅するので、最後の行しか残らない。
- するとどうなるかと言うと、長さが256以上のパケットを受け取ろうとしても取れない。
- パケット長を256で割った余りの分だけ、パケットを取ってしまう(つまり途中)
- 例えば、モード7ですよと言う宣言の場合、
- 正しくはこうなる(最後の括弧内がパケット長)。
- [java]
- 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); [/java] 多分、これでいいと思う。 MatrixLEDを動かしてみたら、ちゃんと動いたし。 2日もエラーを探し続けたので、若干怒りのこもったエントリーになってしまった。 と言うか、今まで誰も気付かなかったのか?
最新コメント