charset of this page is UTF-8
というわけで、 serial_midi の multiport 対応が一息ついたようなので、ほったらかしになっていた KTV をいじり始めています。が、ここのところ調子が悪かったモニターが、先日ついに本格的におかしくなってしまいました。青がでなくなっちゃって、画面が真黄色です。目が痛いです。辛いです。頭も痛くなります。青系統のサングラスをかければ青が出てないことが気にならないかと思ったんですが、世の中そんなに甘くはありませんでした(あたりまえ)。
ありがたいことに多くの方から動作報告をいただきました。外国の方からもいただいたんですが、どのグラフィックスカードを使っているか書いてないところをみると、たまたま見つけて拾っていっちゃったみたいです。で、いただいた結果を見ると、 Matrox G200 と ATI 3D Rage Pro Turbo が okay のようです。 KTV が使える条件は、これらのカードを使っており、表示用以外に Bitmap Overlay 用の領域 (640 x 480 x 2 = 61440 = 600 KBytes) が取れるだけのメモリがカードに載っているということのようです。
KTV 動作中にスクリーンの設定を変えると、 KTV の表示が止まったり、おかしくなったり、 KTV のウィンドウをはみ出してスクリーン中央辺りにノイズが出たりします。あと、たとえば 640 x 480 x 8bit のワークスペースで KTV を動かしていて、 KTV はそのワークスペースに置いたままで 1024 x 768 x 32bit のワークスペースに切り替えたりしても、 KTV のウィンドウをはみ出してスクリーン中央辺りにノイズが出たりします。これらの原因は共通で、スクリーンの設定が変わったためフレームバッファ内での Bitmap Overlay 用領域の位置が変ったにもかかわらず、 media node で使っているバッファが以前の Bitmap Overlay 用領域を指しているために起きます。つまり、低解像度では画面表示用の領域外にあった Bitmap Overlay 用の領域の位置を、高解像度にしたときにもそのまま指し続けているために画面表示用の領域と重なってしまい、スクリーン上にノイズのように表示されてしまうわけです。これを避けるには B_SCREEN_CHANGED とかをフックしてやって、 media node で使うバッファ を作り直してあげればよいということになります。
これ以外に、 G200 で、高解像度あるいは高リフレッシュレートの時に、 KTV の表示にノイズがのるというのもありますが、こちらは mplay でも同様なのでドライバの問題じゃないかと思います。
node での BufferGroup 作成はこんなふうになります。
// Bitmap Overlay 用の BBitmap を作る
mBitmap = new BBitmap(BRect(0, 0, mWidth - 1, mHeight - 1), B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL, aSpace, mRowBytes);
if ((mBitmap->InitCheck() == B_OK) && mBitmap->IsValid()) {
// このとき、 mBitmap->Bits() の実体ははカード上にある
buffer_clone_info aCloneInfo;
aCloneInfo.buffer = 0;
// mBitmap->Bits() がいる area を調べて
aCloneInfo.area = area_for(mBitmap->Bits());
area_info aAreaInfo;
get_area_info(aCloneInfo.area, &aAreaInfo);
// その area 内の Bitmap Overlay 用領域のオフセットを計算
aCloneInfo.offset = ((char*)mBitmap->Bits()) - ((char*)aAreaInfo.address);
aCloneInfo.size = mBitmap->BitsLength();
aCloneInfo.flags = 0;
// area の情報をもとに BufferGroup に Buffer を追加
mInputBuffers->AddBuffer(aCloneInfo);
}
あとはキャプチャーカードとグラフィックスカードにおまかせ。 consumer node の HandleEvent() の中の B_HANDLE_BUFFER イベントの処理は、なぁんにもせずにひたすらバッファを Recycle() するだけ。
case BTimedEventQueue::B_HANDLE_BUFFER:
{
BBuffer* aInBuffer = (BBuffer*)event->pointer;
if (aInBuffer != NULL)
aInBuffer->Recycle();
}
break;
なんか、無茶苦茶単純です。
で、既知の問題の所で書いたようなことをちょこっと対応し 10/30 版を作ってみました。なんとなく B_ALL_WORKSPACES にしてみたりしてます。まだ体裁が整ってないんですが。コントロールウィンドウを閉じちゃうとそれまでだし、ワークスペース切換でちょっとノイズが残ったりしてますけど、絵が止まっちゃったりすることは無いと思います。画面に出たごみは、適当なウィンドウでずりずりと掃除してやれば (つまり、一度リドロウしてやれば) 消えます。
1999-10-30
KISAKA Toshihiro