用编程创建的Windows媒体播放器进行基本播放

时间:2009-12-20 14:23:03

标签: c++ windows com atl windows-media-player

我试图通过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

2 个答案:

答案 0 :(得分:3)

WMP支持两种自动化方法,即嵌入式ActiveX或COM服务器。 对于嵌入式使用,您可以通过对象标记添加ActiveX(通过BHO / Band中的IHTMLWindow2执行一些脚本)或隐藏的表单并从那里自动执行。有关示例代码,请参阅Using the Windows Media Player Control in a Web PageHosting the Windows Media Player Control in a Windows Application

对于COM服务器使用,只需将播放器创建为COM服务器并从中自动执行。 您可以make it a UI-less playback engineremote 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,这显然会导致相当多的组件在进程内创建时失败。