我试图通过COM “快速集成” Windows Media Player来播放本地文件系统或HTTP源中的单个文件 – 但是由于稀疏的文档和在线资源的使用,当没有embedded某种types的Ole容器时,我无法得到所谓的微不足道的用例。
初始化等工作正常,但实际上播放一些文件总是失败。
示例代码,从初始化开始(剥离的error handling,基本上从MSDN上的C#示例转换,在主线程上执行):
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
。
我偶然发现了一个线程,表明multithreading可能无法正常使用WMP,并且此代码在multithreading的公寓中运行。 这可能是问题吗?
如果没有,还有什么可以阻止WMP播放文件?
着名的背景:
WMP实例是在一个以浏览器作为主机进程的DLL中创build的。
更新:
尝试普通的DirectShow,WMP应该使用自己,显示出一个更具体的问题 – 看到这个问题 。
WMP支持两种自动化方法,即嵌入式ActiveX或COM服务器。 对于嵌入式使用,您可以通过对象标签(通过BHO / Band中的IHTMLWindow2执行一些脚本)或隐藏窗体来添加ActiveX,并从中自动执行。 请参阅在网页中使用Windows Media Player控件并在Windows应用程序中托管Windows Media Player控件以获取示例代码。
对于COM服务器的使用,只需创建播放器作为COM服务器,并从它自动化。 您可以将其设置为无UI的播放引擎 ,也可以将其设置为 遥控,以便您拥有完整的用户界面 。
Windows媒体播放器异步播放,例如,它可以调用IMediaControl :: Run并在您调用put_URL时立即返回(另一个立即调用播放将失败,因为它已经播放)。 如果你不需要自动播放,我想你需要IWMPSettings :: put_autoStart。
WMP认为自己是主线。 如果你在一个工作者线程或MTA线程中,我建议你跨越另一个进程来自动化它,或者把它作为一个out-proc服务器来远程执行。
经过进一步的调查 ,事实证明,这实际上是VS2008解决方案造成的VS2008 AtlSetPerUserRegistration()
,它始终是活动 – 但应该只为所包含的COM服务器注册/注销。
解决方法是用HKEY_CURRENT_USER
覆盖HKEY_LOCAL_MACHINE
,这显然会导致相当多的组件失败,如果它们是在进程中创建的。