Windows Media Player用の視覚エフェクト(Visualizer)の作り方が面白そうだったので、ちょっと視覚エフェクトを使って遊んでみました。
すると、
こんな感じになりました。
まあ初めてにしてはうまくやれたんじゃないかと自作自演、じゃなくて自画自賛です。
研究課題として、しばらくはこの視覚エフェクトのことについて書いていこうと思います。
今日はこの視覚エフェクトの概要について書いていこうと思います。
もしかしたら嘘も混じってるかもしれないので話半分ぐらいに聞いておいた方が良いかもしれません。
Windows Media Player(以下 WMP)と視覚エフェクトは COM でやりとりを行うので、視覚エフェクトは COM の流儀に従って組んでやる必要があります。
WMP は視覚エフェクトの一覧を以下のレジストリから探し出します。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MediaPlayer\Objects\Effects
つまり視覚エフェクトを実装する側は、必ずこのキーに情報を書く必要があります。そうしないと WMP に視覚プラグインが認識されません。
この Effects キーのサブキーとしてアプリ名(今回の場合は WmpTest という名前にした)があり、そのサブキーに Property というキーがあります。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MediaPlayer\Objects\Effects\WmpTest\Property
このキーの値として classid というのがあり、ここにプラグイン本体の CLSID を記述します。
WMP はこの CLSID を使って ::CoCreateInstance をするので、CLSID に対応する dll や exe のパスもレジストリに記述しておく必要があります。
ATL が使用できるのであれば、レジストリスクリプト(*.rgs ファイル)を使って CLSID の登録と Effects 以下にキーを書き込むスクリプトを用意すればいいと思います。Wizard が生成するサンプルもそうなっています。
Proxy/Stub は、WMP が視覚エフェクトをシングルスレッドアパートメントで使っているみたいなので、視覚エフェクトがインプロセスサーバで ThreadingModel が Apartment や Both である限りは必要無いみたいです。
で、WMP は ::CoCreateInstance で視覚エフェクトを生成するわけですが、そのときに必ず実装している必要のある COM インターフェースは IWMPEffects です。
好みに応じて IWMPEffects2 を実装しても構いません。ただし、IWMPEffects2 は WMP9 で追加されたインターフェースなので、それ以前のバージョンではこのインターフェースは呼ばれないことに注意です。
WMP は IWMPEffects を通じて、いくつかの情報を取得します。
IWMPEffects::GetTitle を使って、この視覚エフェクトのタイトルを取得します。ただ、どこで使われてるかは知りません。
IWMPEffects::GetPresetTitle を使って、各プリセットのタイトルを取得します。プリセットについては後述します。
IWMPEffects::GetPresetCount を使って、プリセットの総数を取得します。IWMPEffects::GetPresetTitle 等に渡されるプリセット値は、この総数以上になることはありません。
IWMPEffects::GetCapabilities を使って、この視覚エフェクトの持っている機能を取得します。
WMP は EFFECT_CANGOFULLSCREEN が指定されていると、視覚エフェクトは全画面で表示できると解釈します。
EFFECT_HASPROPERTYPAGE が指定されていると、視覚エフェクトはプロパティページがあると解釈します。
EFFECT_VARIABLEFREQSTEP が指定されていると、視覚エフェクトに対して渡す周波数データは可変長で扱う必要があると解釈します。
プリセットについてですが、これは同じ視覚エフェクトの中で違う効果を見せる場合に使います。
というかプリセットについては画像を見た方が早いのですが、
この画像の、TestEffects と書いてある部分が1つの視覚エフェクトで、この中にある maxCount = xx... とあるのが各プリセットになっています。
各プリセットを選択すると、WMP は IWMPEffects::SetCurrentPreset でプリセットを視覚エフェクトにセットするので、視覚エフェクトはそのプリセットに応じた描画をすればいいのです。
実際の描画は IWMPEffects::Render で行います。
WMP は定期的に IWMPEffects::Render メソッドを呼び出すので、視覚エフェクトは引数として渡された TimedLevel 構造体を利用して(利用しなくてもいいけど)実際の描画を行います。
値によって色を変えたりしながら描画を行うと、↑の画像みたいなエフェクトが表現出来るようになります。
次は実際のコードも含めてもう少し細かく書いていこうと思います。