Я парень, который был здесь некоторое время назад , спрашивающий об управлении Windows Media Player через Java. Я добился прогресса, но столкнулся с неприятной проблемой, поэтому я снова смотрю за помощь.
Я последовал совету, который получил в прошлый раз, и установил Джейкоба. Я выполняю эти строки из тестового скрипта:
ActiveXComponent wmp = new ActiveXComponent("WMPlayer.OCX");
wmp.invoke("openPlayer", "http://somafm.com/wma128/groovesalad.asx");
... и 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"));
... Я получаю вывод:
VOLUME: 50
VOLUME: 0
Это кажется достаточно безобидным, за исключением того, что
- громкость "50" не имеет ничего общего
с тем, где громкость проигрывателя
на самом деле установлен и
- громкости плеера нет
на самом деле изменить после
Вызов setProperty.
Я пробовал и другие свойства, но это то же самое: значение свойств, похоже, не связано с тем, что на самом деле делает игрок, и при изменении их, кажется, изменяется состояние объект , которым манипулируют, не влияет на фактического игрока . (каждый раз при запуске скрипта я получаю один и тот же вывод, поэтому, что бы я ни изменял, меняю при повороте) том ", он не имеет никакого постоянства вне кода.)
Очевидно, я делаю что-то не так, но я слоняюсь без дела, пытаясь понять, что. Кто-нибудь может предложить мне какое-нибудь понимание того, что происходит не так, или что я должен попробовать дальше?
(Примечание: я даже не уверен, что "WMPlayer.OCX" является правильным входным параметром. Я экспериментировал с вероятными записями в HKEY_CLASSES_ROOT в реестре, пока не нашел этот.)
Заранее благодарю за любую помощь, которую кто-либо может предложить.
Редактировать, 15.04.2009: Я нашел пакет, специфичный для WMP, в предложениях компании EZ JCom. Он потерпел неудачу способами, столь идентичными тому, что я видел раньше, что это либо просто оболочка для Джейкоба, либо интерфейс WMP ActiveX / COM просто сломан. (Подожди, почему я сказал "либо"?)
Я поболтал со службой поддержки, и они продемонстрировали, как вы можете быть полезными, не будучи на самом деле полезными. Они помогли мне исправить некомпилируемый пример кода, который они предоставили в качестве примера своего кода WMP в действии, но когда я приставил к ним для некоторого понимания того, как методы get / set volume должны работать, я получил это:
«Извините, но здесь нет подробных сведений о WMP - EZ JCom является просто мостом между Java и другими программами, такими как WMP».
Имейте в виду, что пакет, который я оценивал, на самом деле называется "wmp.WindowsMediaPlayer". Если бы я заставил его работать, мне пришлось бы уговорить моего босса выложить 600 долларов за лицензию. Интересно, что бы они взяли, если бы у них был какой-то опыт в их собственном продукте?
Итак, реального прогресса нет. Просто думал, что поделюсь.
Редактировать, 20.04.2009: Да, я все еще ткнись в это. Моя текущая теория работы заключается в том, что для настройки громкости мне потребуется удаленный доступ к WMP. Я видел упоминание об интерфейсах IWMPRemoteMediaServices и IServiceProvider, причем метод QueryService последнего предоставляет указатель на первый. К сожалению, мне не повезло выяснить, как завладеть IServiceProvider. Я видел упоминание о том, что он доступен из окна «Система» объекта, но я не могу понять, как получить этот объект. (И поскольку слово «система» в значительной степени относится к Java, Google дает мне отношение шум: сигнал.) Если у кого-нибудь есть какие-либо советы о том, как я возлагаю руки на COM-объект, представляющий System.dll, я бы с удовольствием услышь это.
Редактировать, 21.04.2009: Уточнение: это в системе XP.
Кроме того: мое исследование предполагает, что простого разговора с объектом WMP недостаточно; Вы должны обернуть это более плотно чем это, чтобы это могло говорить. Существует WMP SDK с большим количеством C ++, но, похоже, он полагается на расширения Microsoft Visual C ++ для кода, которого у меня нет, и они не раздаются бесплатно. (Кроме того, я не делал C ++ в течение двенадцати лет.) Я знаю, что это возможно с C #, но если я выхожу за пределы Java, мне нужно, чтобы решение было автономным исполняемым файлом, а .NET не установлен на соответствующие машины.
Edit, 22.04.2009: Согласно ответу Марка, приведенному ниже, я вытащил константы APPCOMMAND_MEDIA_ * из WinUser.h и попробовал следующий код, который использует 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
Find Window Error? null
Play Result: -1
Play Error? null
Pause Result: -1
PauseError? null
... но фактически не влияет на медиаплеер.
Я также пробовал это с APPCOMMAND_MEDIA_PLAY_PAUSE (14), который дает разные возвращаемые значения (20), но также ничего не делает.
FWIW, мне действительно нужно заставить работать отдельные команды PLAY / PAUSE, чтобы это было приемлемым вариантом; простое переключение состояния вслепую не помогает мне, так как я не знаю, в каком состоянии находится игрок, когда я начинаю.
У кого-нибудь есть советы, что я делаю неправильно или что еще я могу попробовать?