我试图通过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,但实际上没有播放:
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.
解决方法:
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线程中,我建议您跨越另一个进程来自动化它,或将其远程作为一个进程外服务器.