Bla*_*ppo 7 activex windows-media-player
我曾经在这里问过有关通过Java控制Windows Media Player的问题. 我已经取得了进步,但我遇到了一个棘手的问题,所以我回来寻求帮助.
我按照上次给出的建议,安装雅各布.我从测试脚本中执行这些行:
ActiveXComponent wmp = new ActiveXComponent("WMPlayer.OCX");
wmp.invoke("openPlayer", "http://somafm.com/wma128/groovesalad.asx");
Run Code Online (Sandbox Code Playgroud)
...和WMP弹出,玩SomaFM."W00t!" 我认为."我已经解决了这个问题!"
除了当我在创建它之后与该对象交互时,它似乎与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"));
Run Code Online (Sandbox Code Playgroud)
...我得到的输出:
VOLUME: 50 VOLUME: 0
这似乎无害,除此之外
我也尝试了其他属性,但它是一样的:属性的值似乎与玩家实际做的事情没有关系,而改变它们似乎改变了被操纵对象的状态,它对实际玩家没有影响. (每次运行脚本时,我都得到完全相同的输出,所以无论是什么,当我转动"音量"时我都会改变它,它在代码之外没有任何持久性.)
显然我做错了什么,但我一直摸索着试图找出什么.任何人都可以向我提供任何有关出错的信息,或者我接下来应该尝试的内容吗?
(注意:我甚至不确定"WMPlayer.OCX"是正确的输入参数.我在注册表中的HKEY_CLASSES_ROOT中试验了看起来很可能的条目,直到找到这个.)
我提前感谢任何人提供的任何帮助.
编辑,4/15/2009: 我在一家名为EZ JCom的公司的产品中找到了一个特定于WMP的软件包.它失败的方式与我之前看到的完全相同,要么它只是Jacob的包装器,要么是WMP ActiveX/COM接口完全坏了.(等等,为什么我说"要么"?)
我与客户服务人员聊天,他们最终展示了如何在没有实际用处的情况下提供帮助.他们帮助我纠正了他们提供的非编译示例代码作为他们的WMP代码的实例,但是当我纠缠他们以了解get/set卷方法应该如何工作时,我得到了这个:
"对不起,但这里没有WMP深度专业知识--EZ JCom只是Java与WMP等其他程序之间的桥梁建设者."
请记住,我评估的他们的包实际上被称为"wmp.WindowsMediaPlayer".如果我得到它的工作,我将不得不与我的老板谈论花费600美元的许可证.人们想知道如果他们真正拥有自己产品的专业知识,他们会收取什么费用.
所以,没有真正的进步.只是想我会分享.
编辑,2009年4月20日: 是的,我仍然在嘲笑这个.我目前的操作理论是,为了获得音量设置,我需要远程访问WMP.我已经看到了IWMPRemoteMediaServices和IServiceProvider接口的提及,后者的QueryService方法提供了指向前者的指针.不幸的是,我没有任何关于如何获得IServiceProvider的运气.我已经看到提到它可以从Windows"系统"对象访问,但我无法弄清楚如何获取该对象.(而且由于"系统"这个词在Java中非常重要,谷歌给了我一个喧闹的声音:信号比率.)如果有人对如何把手放在代表System.dll的COM对象上有任何建议,我很乐意听到.
编辑,4/21/2009: 澄清:这是在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());
Run Code Online (Sandbox Code Playgroud)
这给了我一个结果:
wmpHandle: 1640048 Find Window Error? null Play Result: -1 Play Error? null Pause Result: -1 PauseError? null
...但实际上并不影响媒体播放器.
我也尝试过APPCOMMAND_MEDIA_PLAY_PAUSE(14),它给出了不同的返回值(20),但也没有做任何事情.
FWIW,我真的需要让单独的PLAY/PAUSE命令工作才能成为一个可行的选择; 盲目地简单地切换状态对我没有帮助,因为当我开始时我不知道玩家处于什么状态.
有没有人对我做错了什么或者我可能会尝试什么有任何建议?
那么这些都不起作用吗?
wmp.getProperty("settings").toDispatch().setProperty("mute", 1);
wmp.getProperty("controls").toDispatch().invoke("pause");
Run Code Online (Sandbox Code Playgroud)
(对错误代码表示歉意;我以前从未使用过 Jacob)
在这种情况下,创建/查找任何窗口并发送它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});
Run Code Online (Sandbox Code Playgroud)
APPCOMMAND_MEDIA_PLAY需要 XP SP1,但我假设您已经部署了。
| 归档时间: |
|
| 查看次数: |
2392 次 |
| 最近记录: |