mciSendStringについてのメモ
今日の4時間くらいを返してくれ・・・。
ゲームライブラリの中でMCIを使う部分を今日は書いていました。テスト期間中だけどね!
まぁMCIを使うのでmciSendStringをexternで宣言して、使いやすいようにメソッドやプロパティの実装をゴリゴリ書いていたわけです。
とりあえずテスト可能な段階まで書き終えたので、まぁ動くわなっていう気構えでデバッグ開始。
はい例外発生ー。文脈的には予想通りーww
音量取得メソッド内で、バッファにぶち込まれた文字列をint.Parse()するところでコケたようです。
とりあえずブレークポイントを設定して、渡されている文字列を見ると空っぽ!え、ちゃんと仕事しろよっていうw
つまりは直前のmciSendStringがキチンと動いてくれていないわけです。
public static int GetVolume(string alias) { mciSendString("status " + alias + " volume", buffer, buffer.Capacity, IntPtr.Zero); return int.Parse(buffer.ToString()); }
そこでmciSendStringをConsole.WriteLine()することに。エラーコードが見れるからね!
こうしてコンソールに表示されたのは263、MSDNによるとMCIERR_INVALID_DEVICE_NAMEというエラーらしい。
不正なデバイス名ってことか。しかし何度確かめても、引数を使わずにリテラルで送信してもエイリアスは合っている・・・。そもそも再生までは行くんだなぁ。
ということで別プロジェクトを作って問題のコードを適当に再現。動くじゃん!なぜ?なぜ?なんでなの?ww
そしてその動いたコードをテスト中のクラスにコピペ。動くじゃん!そしてGetVolume内と比較。同じじゃん!そしてコピペ部分を削除。動かNEEEEEEEEEE!!!!!!
これを3回くらいやった。ググりまくった。そして4時間ほど浪費・・・。
そして・・・!問題の原因が判明した!
- スレッドAでmciSendStringで"open ファイルパス alias sound"を送信。
- スレッドAでmciSendStringで"play sound"を送信。←ここまでは動く
- スレッドBでmciSendStringで"status sound volume"を送信。
- 戻り値が入っているであろうバッファをParseする。←例外発生
要は別スレッドでは動いてくれない!ってことみたい。
なぜ別スレッドなのかというと、ゲームループがスレッドを占有してしまうから。
これはまた何か工夫する必要がありそうだけどとりあえず今日はこのメモを書いて終わり!つかれた!