我试图通过COM “快速集成” Windows Media Player来播放来自本地文件系统或http源的单个文件 - 但由于其使用的文档和在线资源稀少当没有嵌入到某种Ole容器中时,我无法让那些可能是微不足道的用例工作。
初始化等工作正常,但实际播放某些文件总是失败。
示例代码,从初始化开始(错误处理被剥离,基本上从C# example at MSDN翻译,在主线程上执行):
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
第一种播放内容的方法是“命令不可用”:
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
第二种方法只生成S_OK
s,但实际上没有播放:
CComPtr<IWMPMedia> media;
core->newMedia(path, &media);
playlist->appendItem(media);
controls->playItem(media); // returns S_OK, but doesn't play
我注意到的另一件事是core->get_playState()
总是返回wmposMediaOpening
,无论我等多久。
我偶然发现一个线程暗示多线程可能无法正常使用WMP,并且此代码在多线程单元中运行。可能是问题吗?
如果没有,还有什么可能阻止WMP播放文件?
值得注意的背景:
WMP实例是在DLL中创建的,其中浏览器作为主机进程。
更新
尝试使用WMP应该使用的简单DirectShow会出现更具体的问题 - 请参阅question for that。
答案 0 :(得分:3)
WMP支持两种自动化方法,即嵌入式ActiveX或COM服务器。 对于嵌入式使用,您可以通过对象标记添加ActiveX(通过BHO / Band中的IHTMLWindow2执行一些脚本)或隐藏的表单并从那里自动执行。有关示例代码,请参阅Using the Windows Media Player Control in a Web Page和Hosting the Windows Media Player Control in a Windows Application。
对于COM服务器使用,只需将播放器创建为COM服务器并从中自动执行。 您可以make it a UI-less playback engine或remote it so you have a full UI。
Windows Media Player异步播放,例如,它可以调用IMediaControl :: Run并在调用put_URL时立即返回(另一个立即调用play会因为播放而失败)。如果你不需要自动播放,我想你需要IWMPSettings :: put_autoStart。
WMP假设自己处于主线程中。如果你在工作线程或MTA线程中,我建议你跨越另一个进程来自动化它,或者将它作为一个进程外服务器远程。
答案 1 :(得分:0)
在further investigation之后,事实证明这实际上是由VS2005 for AtlSetPerUserRegistration()
的VS2005变通方法引起的,它始终处于活动状态 - 但应该仅用于包含的COM服务器注册/取消注册。
解决方法会将HKEY_LOCAL_MACHINE
替换为HKEY_CURRENT_USER
,这显然会导致相当多的组件在进程内创建时失败。