WMP Redux

You may recall an earlier post in which I was trying to mate WPF with the Windows Media Player (Playing with the WMPSDK). My original thought was to export the time series and spectrum data from WMP to a WPF client app.

That didn't work very well, so I started considering a solution using interop. I started with C++/CLI, but my initial experiments weren't too successful -- for some reason I couldn't register an assembly that was built with the /clr option. Here are the unhappy details:

warning C4747: Calling managed '_DllMain@12': Managed code may not be run under loader lock, including the DLL entrypoint and calls reached from the DLL entrypoint e:\Projects\WMP\wmpplugin2\wmpplugin2\wmpplugin2dll.cpp 1 

error RA0000 : Could not load file or assembly 'wmpplugin2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Exception from HRESULT: 0xE0434F4D RegAsm

error PRJ0050: Failed to register output. Please ensure you have the appropriate permissions to modify the registry. wmpplugin2

I tried the recommended "#pragma unmanaged", which eliminated the warning, but registration still failed.

So I started considered going the other way: implement the the plugin as a managed assembly that exposes COM interfaces. I happened to have a slide deck by Adam Nathan, one of our interop gurus, so I sent him an email asking his opinion.

By cosmic coincidence, Adam was working on the same problem and already had a solution, which he's posted today: Using COM Interop to Create a WPF Visualization for Windows Media Player.

This solution works beautifully, and it opens up all sorts of neat possibilities. I've adapted Adam's solution to render the time series ("oscilliscope") and spectrum ("equalizer"). I was concerned about performance across the managed/unmanaged boundary, but that doesn't seem to be much of an issue -- maybe what we lose there is made up by video card acceleration.

Time series

 

Spectrum

I also learned that when I'm drawing thousands of lines, Polyline is the way to go. Adding a bunch of Line children to the Canvas slows rendering way down, which is not unexpected.

Next steps:

  • Play with animating various dependency properties.
  • Add some other controls into the WPF control and bind them to interesting values like amplitude, key frequency, energy threshold, etc.
  • Try using more sophisticated UI elements like Viewport3D and Image.

I highly recommend playing with Adam's solution. It's educational both as a Win32/WPF interop demonstration and as a managed/COM interop demonstration. Check it out.