【问题标题】:Windows Media Player Ignoring MeWindows Media Player 忽略我
【发布时间】:2010-01-24 01:27:33
【问题描述】:

我是前阵子asking about controlling Windows Media Player via Java.的那个人,我已经取得了进步,但我遇到了一个棘手的问题,所以我回来寻求帮助。

我按照上次得到的建议安装了 Jacob。我从测试脚本中执行这些行:

ActiveXComponent wmp = new ActiveXComponent("WMPlayer.OCX");
wmp.invoke("openPlayer", "http://somafm.com/wma128/groovesalad.asx");

...然后 WMP 弹出,播放 SomaFM。 “哇!”我认为。 “我已经解决了这个问题!”

除了我在创建该对象后与它进行交互时,它似乎与播放 WMP 实例没有任何关系。当我执行这段代码时:

ActiveXComponent wmpSettings = new
ActiveXComponent(wmp.getProperty("settings").toDispatch());
System.out.println("VOLUME: " + wmpSettings.getProperty("volume"));
wmpSettings.setProperty("volume", 0);
System.out.println("VOLUME: " + wmpSettings.getProperty("volume"));

...我得到以下输出:

音量:50 音量:0

这似乎无伤大雅,除了

  1. “50”的音量无关 播放器音量在哪里 实际设置和
  2. 播放器的音量不 实际上改变之后 setProperty 调用。

我也尝试过其他属性,但都是一样的:属性的值似乎与玩家实际在做什么无关,而更改它们似乎会改变 object 被操纵,它对实际的 player 没有影响。 (我每次运行脚本时都会得到完全相同的输出,所以无论我在改变什么时旋转“音量”,它在代码之外没有任何持久性。)

显然我做错了什么,但我盲目地摸索着想弄清楚是什么。任何人都可以告诉我发生了什么问题,或者我接下来应该尝试什么?

(注意:我什至不确定“WMPlayer.OCX”是正确的输入参数。我在注册表中的 HKEY_CLASSES_ROOT 中尝试了看起来很可能的条目,直到找到这个。)

我提前感谢任何人可以提供的任何帮助。


编辑,2009 年 4 月 15 日:我在一家名为 EZ JCom 的公司的产品中发现了一个 WMP 特定的包。它失败的方式与我之前看到的完全相同,要么它只是 Jacob 的包装器,要么 WMP ActiveX/COM 接口完全损坏。 (等等,我为什么说“要么”?)

我与客户服务人员聊天,他们最终向您展示了如何在没有实际帮助的情况下提供帮助。他们帮助我更正了他们提供的非编译示例代码,作为他们的 WMP 代码运行示例,但是当我纠缠他们以了解 get/set volume 方法应该如何工作时,我得到了这个:

“抱歉,这里没有 WMP 深入的专业知识 - EZ JCom 只是 Java 和 WMP 等其他程序之间的桥梁。”

请记住,我正在评估的他们的软件包实际上称为“wmp.WindowsMediaPlayer”。如果我让它发挥作用,我将不得不说服我的老板花 600 美元购买许可证。有人想知道,如果他们真的对自己的产品有一定的专业知识,他们会收取多少费用。

所以,没有真正的进展。只是想我会分享。


编辑,2009 年 4 月 20 日: 是的,我还在纠结这个。我目前的操作理论是,为了获得音量设置,我需要远程访问 WMP。我见过提到 IWMPRemoteMediaServices 和 IServiceProvider 接口,后者的 QueryService 方法提供了指向前者的指针。不幸的是,我没有任何运气弄清楚如何获得 IServiceProvider。我已经看到提到它可以从 Windows“系统”对象访问,但我不知道如何获取该对象。 (而且由于“系统”这个词在 Java 中占了相当大的比重,谷歌给了我一个可怕的噪音:信号比。)如果有人对我如何处理表示 System.dll 的 COM 对象有任何建议,我很乐意听听。


编辑,2009 年 4 月 21 日: 澄清:这是在 XP 系统上。

另外:我的研究表明仅仅与 WMP 对象对话是不够的;你需要把它包得更紧,这样它才能回话。有一个包含很多 C++ 内容的 WMP SDK,但它似乎依赖于 Microsoft Visual C++ 对我没有的代码的扩展,而且它们并不是免费赠送的。 (此外,我已经有 12 年没有使用过 C++了。)我知道 C# 是可能的,但是如果我不使用 Java,我需要该解决方案是一个独立的可执行文件,并且没有安装 .NET相关机器。


编辑,2009 年 4 月 22 日: 根据 Mark 在下面的回答,我从 WinUser.h 中挖出了 APPCOMMAND_MEDIA_* 常量并尝试了以下代码,该代码使用了 NativeCall api:

final int APPCOMMAND_MEDIA_PLAY = 46;
final int APPCOMMAND_MEDIA_PAUSE = 47;

NativeCall.init();

IntCall findWindow = new IntCall("user32", "FindWindowA");
int wmpHandle = findWindow.executeCall(new Object[] { null, "Windows Media Player" });
System.out.println("wmpHandle: " + wmpHandle);
System.out.println("Find Window Error? " + findWindow.getLastError());

IntCall sendMessage = new IntCall("user32", "SendMessageA");

int playResult = sendMessage.executeCall(new Object[] { wmpHandle, APPCOMMAND_MEDIA_PLAY, 0, 0 });
System.out.println("Play Result: " + playResult);
System.out.println("Play Error? " + sendMessage.getLastError());

try { Thread.sleep(5000); } catch (Exception e) {}

int pauseResult = sendMessage.executeCall(new Object[] { wmpHandle, APPCOMMAND_MEDIA_PAUSE, 0, 0 });
System.out.println("Pause Result: " + pauseResult);
System.out.println("PauseError? " + sendMessage.getLastError());

这给了我一个结果:

wmpHandle: 1640048 查找窗口错误?无效的 播放结果:-1 播放错误?无效的 暂停结果:-1 暂停错误?无效的

...但实际上并不影响媒体播放器。

我也尝试过使用 APPCOMMAND_MEDIA_PLAY_PAUSE (14),它给出不同的返回值 (20),但也不执行任何操作。

FWIW,我真的需要让单独的 PLAY/PAUSE 命令来工作,这才是一个可行的选择;只是盲目地切换状态对我没有帮助,因为我不知道当我开始时玩家处于什么状态。

有人对我做错了什么或我可以尝试什么有任何建议吗?

【问题讨论】:

  • 好吧,我对你的问题没什么可说的,只是想支持你。
  • 很抱歉,您似乎真的很沮丧,我能理解为什么。所以希望我能帮忙,但我没有这方面的经验。只是觉得我需要给你一点精神上的支持,即使我在这方面的投入实际上是无用的。希望你能度过难关!
  • 感谢你们俩;感谢您的支持。 :-)
  • 这是在 Vista 还是 XP 上运行?
  • XP。可能值得一提,谢谢。

标签: activex windows-media-player


【解决方案1】:

所以这些都行不通吗?

wmp.getProperty("settings").toDispatch().setProperty("mute", 1);
wmp.getProperty("controls").toDispatch().invoke("pause");

(抱歉代码不正确;我以前从未使用过 Jacob)


在这种情况下,创建/find 任何窗口和send 它APPCOMMAND_MEDIA_PLAY_PAUSE。默认消息处理将使其影响 WMP。 (发送静音不好,因为这会使整个系统静音。)

为了可移植性,我建议创建一个 C++ 命令行实用程序或使用 JNI,但现在NativeCall 可能就足够了。


您的代码看起来不错,但我认为您只需将参数更改为 SendMessage。试试:

final int WM_APPCOMMAND = 0x0319;
int playResult = sendMessage.executeCall(new Object[] {
        wmpHandle,
        WM_APPCOMMAND,
        wmpHandle,
        APPCOMMAND_MEDIA_PLAY << 16});

APPCOMMAND_MEDIA_PLAY 需要 XP SP1,但我假设您已经部署了它。

【讨论】:

  • 我非常真诚地希望。 :-) 抱歉不行。进一步的研究表明,基本上,当你尝试以这种方式与 WMP 交谈时,它会反问问题——如果它不喜欢你所说的话,它会忽略你。 (这与我的经验是一致的。)执行这些命令就像在玩一个连接到沙箱的玩具方向盘;你可以随心所欲地旋转它,但实际上什么也没发生。
  • 是的,你可能需要实现 IWMPRemoteMediaServices,我猜 Jacob 做不到。
  • 谢谢!这是我以前没有考虑过的一种方法,但不幸的是,它还没有完全奏效。请查看上面编辑过的帖子,如果您对我是如何搞砸的有任何见解,请告诉我。
  • 哦,是的。先生,你赢了一块饼干。我最深切的感谢;我看起来像个天才,我们的客户会更开心;两者都非常好。最后一对额外的问题:你知道这个技巧是否适用于在浏览器中运行的媒体播放器吗?当我不知道窗口的确切名称时,您知道如何使用 FindWindow 抓取 Internet Explorer 的实例吗?只要我口袋里有这个解决方案,不妨看看它还能做什么。 :-)
  • 顺便说一句,您是否有特定的资源用于编写该代码,或者这主要是您的经验?
【解决方案2】:

当您将 wmpSettings 实例化为新的 ActiveXComponent,Jacob 实际上是在做一些有趣的事情,将组件包装在一个新的媒体播放器对象中,而不是检索您要求的设置属性。

你试过简单吗:

Dispatch wmpSettings = wmp.getProperty("settings").toDispatch();
wmpSettings.setProperty("volume", 0);

我还回去阅读了让您开始使用 Jacob 的原始问题,我可以建议一种不同的方法,以防您在此问题上旋转太久。

我设置了一个 Web 应用程序,该应用程序与当前登录到 Web 应用程序服务器的特定用户桌面上的 winamp 运行的直播服务器进行交互。我无法使用 COM 从 Web 应用程序的上下文中直接与用户的 winamp 实例通信,因此我设置了一个简单的 C# TCP/IP winamp 桥应用程序,该应用程序在shoutcast 用户的桌面上运行并允许 Web 应用程序创建一个来自本地主机的套接字连接。

对于 WMP,我相信您可以找到一些 C# 包装器,例如 WmpRemote.zip 的代码,如果您在 http://d.hatena.ne.jp/punidama/20080227 上进行文本搜索,您可以找到

如果您需要任何具体示例来进行设置,请告诉我。

【讨论】:

  • 您好,感谢您的反馈。您建议的代码无法编译(没有诸如 Dispatch.setProperty() 之类的东西),但是这样做:“Dispatch.put(wmpSettings, "volume", 0);"不幸的是,产生与以前完全相同的行为
  • 您知道任何这样的 C# 包装器已被编译为作为独立应用程序运行吗?将 .NET 部署到需要运行它的所有机器上不是一种选择。 (我承认我对 C#/.NET 了解不多,所以如果这是一个愚蠢的问题,我深表歉意。:-))
猜你喜欢
  • 2014-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多