使用以编程方式创建的 Windows 媒体播放器进行基本播放
Posted
技术标签:
【中文标题】使用以编程方式创建的 Windows 媒体播放器进行基本播放【英文标题】:basic playback with programmatically created windows media player 【发布时间】:2010-12-28 12:03:44 【问题描述】:我试图“快速集成” Windows Media Player 通过 COM 来播放来自本地文件系统或 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。
【问题讨论】:
【参考方案1】: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 线程中,我建议您跨越另一个进程以使其自动化,或者将其作为进程外服务器进行远程处理。
【讨论】:
终于有一些反馈了,谢谢。我正在尝试将其作为无 ui 的 in-proc-COM-server 运行。 WMP 在主线程上创建,并且 put_URL() 也在那里发生。然而,即使等待很长时间,查询打开状态总是会得到wmposMediaOpening
,并且它永远不会开始播放(不管我是否调用play()
)。有什么想法吗?
我建议你远程 WMP 并以同样的方式自动化它,看看你是否收到任何消息框。【参考方案2】:
在further investigation 之后,事实证明这实际上是由 VS2008s AtlSetPerUserRegistration()
的 VS2005 解决方法引起的,它始终处于活动状态 - 但应该只用于包含的 COM 服务器注册/注销。
解决方法用HKEY_CURRENT_USER
覆盖HKEY_LOCAL_MACHINE
,如果在进程中创建它们显然会导致相当多的组件失败。
【讨论】:
以上是关于使用以编程方式创建的 Windows 媒体播放器进行基本播放的主要内容,如果未能解决你的问题,请参考以下文章
使用以编程方式创建的自定义 UITableViewController 管理 UITableView
使用以编程方式创建的 segue IOS 调用自定义过渡动画师