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

  • このエントリーをはてなブックマークに追加
  • 0

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

・・・

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

ActionScript

  1. 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バイトがパケット長なのだが、
そのパケット長の計算がこのようになっている。

  1. int packetSize = ((buffer[processedSize + 0] << 24) & 0xFF)
  2.         + ((buffer&#91;processedSize + 1&#93; << 16) & 0xFF)
  3.         + ((buffer&#91;processedSize + 2&#93; << 8) & 0xFF)
  4.         + (buffer&#91;processedSize + 3&#93; & 0xFF);
  5.  
  6. &#91;/java&#93;
  7. これがダメだ。
  8. よく見ると分かるが、最後の<code>(buffer[processedSize + 3] & 0xFF)</code>以外は
  9. 全部0になる。
  10. 例えば、<code>buffer[processedSize + 0]</code>の値が255(0xFF)だとすると、
  11. (buffer[processedSize + 0] << 24)は0xFF000000になる。
  12. で、<code>0xFF000000 & 0xFF</code>なので、答えは0になる。
  13. この調子で上3行が全滅するので、最後の行しか残らない。
  14. するとどうなるかと言うと、長さが256以上のパケットを受け取ろうとしても取れない。
  15. パケット長を256で割った余りの分だけ、パケットを取ってしまう(つまり途中)
  16. 例えば、モード7ですよと言う宣言の場合、
  17. 正しくはこうなる(最後の括弧内がパケット長)
  18. [java]
  19. 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はこうなる。

  1. 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日もエラーを探し続けたので、若干怒りのこもったエントリーになってしまった。 と言うか、今まで誰も気付かなかったのか?

スポンサーリンク
スポンサーリンク
  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
スポンサーリンク