I was trying to "just quickly integrate" the Windows Media Player via COM to play single files from the local file system or http sources - but due to the sparse documentation and online resources to its usage when not embedding into some kind of an Ole container, i couldn't get that supposedly trivial use-case to work.
Initialization etc. works fine, but actually playing some file always fails.
Example code, starting with initialization (error handling stripped, basically translated from the C# example at MSDN, executed on the main thread):
CComPtr<IWMPPlayer> player;
player.CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER);
CComQIPtr<IWMPCore3> core(player);
CComPtr<IWMPControls> controls;
core->get_controls(&controls);
CComPtr<IWMPPlaylist> playlist;
core->get_currentPlaylist(&playlist);
CComBSTR path("c:\\bar.mp3"); // alternatively http://foo/bar.mp3
The first approach to play something gives "command not available":
core->put_url(path);
// ... waiting after that for WMP to load doesn't make a difference
controls->play(); // returns 0x000D1105 - NS_S_WMPCORE_COMMAND_NOT_AVAILABLE
The second approach only produces S_OK
s, but nothing is actually played:
CComPtr<IWMPMedia> media;
core->newMedia(path, &media);
playlist->appendItem(media);
controls->playItem(media); // returns S_OK, but doesn't play
Another thing i noted is that core->get_playState()
always returns wmposMediaOpening
, no matter how long i wait.
I've stumbled upon one thread that suggests multi-threading might not work properly with WMP and this code runs in a multi-threaded apartment. Might that be the problem?
If not, what else could be preventing WMP from playing the files?
Notable background:
The WMP instance is created in a DLL with a browser as the host-process.
Update:
Trying plain DirectShow, which WMP should be using itself, exhibits a more specific problem - see the question for that.
WMP supports two automation methods, embedded ActiveX or COM server. For embedded use, you add the ActiveX via an object tag (execute some scripts via IHTMLWindow2 from your BHO/Band) or a hidden form and automate from there. See Using the Windows Media Player Control in a Web Page and Hosting the Windows Media Player Control in a Windows Application for sample codes.
For COM server use, just create the player as COM server and automate from it. You can either make it a UI-less playback engine, or remote it so you have a full UI.
Windows Media Player plays asynchronously, for example, it could call IMediaControl::Run and return immediately when you call put_URL (another immediate call to play would fail because it is already playing). If you do not need the automatic playing, I guess you need IWMPSettings::put_autoStart.
WMP assumes itself to be in the main thread. If you are in a worker thread or a MTA thread, I suggest you span another process to automate it, or remote it as an out-of-proc server.
After further investigation, it turned out that this was actually caused by a VS2005 workaround for VS2008s AtlSetPerUserRegistration()
which was always active - but should have been only for the contained COM servers registration/unregistration.
The workaround overrides HKEY_LOCAL_MACHINE
with HKEY_CURRENT_USER
, which obviously results in quite some components failing if they are created in-process.
User contributions licensed under CC BY-SA 3.0