【发布时间】: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这似乎无伤大雅,除了
- “50”的音量无关 播放器音量在哪里 实际设置和
- 播放器的音量不 实际上改变之后 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