Проигрыватель Windows Media игнорирует меня - PullRequest
7 голосов
/ 14 апреля 2009

Я парень, который был здесь некоторое время назад , спрашивающий об управлении 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

Это кажется достаточно безобидным, за исключением того, что

  1. громкость "50" не имеет ничего общего с тем, где громкость проигрывателя на самом деле установлен и
  2. громкости плеера нет на самом деле изменить после Вызов 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, чтобы это было приемлемым вариантом; простое переключение состояния вслепую не помогает мне, так как я не знаю, в каком состоянии находится игрок, когда я начинаю.

У кого-нибудь есть советы, что я делаю неправильно или что еще я могу попробовать?

Ответы [ 2 ]

2 голосов
/ 21 апреля 2009

Так они не работают?

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

(извиняюсь за неправильный код; я никогда раньше не использовал Джейкоба)


В этом случае создайте / найдите любое окно и отправьте it 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, но я предполагаю, что вы развернули его.

1 голос
/ 15 апреля 2009

похоже, когда вы создаете экземпляр wmpSettings как новый ActiveXComponent, Джейкоб на самом деле делает что-то смешное, чтобы обернуть компонент в новый объект медиаплеера, вместо того, чтобы получить требуемое свойство настроек.

Вы пробовали просто:

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

Я также вернулся и прочитал оригинальный вопрос, который заставил вас использовать Джейкоба, и я могу предложить другой подход на случай, если вы закрутите колеса на этом слишком долго.

Я настроил веб-приложение, которое взаимодействовало с сервером shoutcast, запущенным из winamp, на рабочем столе определенного пользователя, который в настоящее время вошел в систему на сервере веб-приложений. Я не мог использовать COM для прямой связи с экземпляром winamp пользователя из контекста веб-приложения, поэтому я установил простое приложение winamp bridge C # TCP / IP, которое запускалось на рабочем столе пользователя shoutcast и позволяло веб-приложению создавать сокет подключения от localhost.

Для WMP я уверен, что вы можете найти некоторые обертки C #, такие как код для WmpRemote.zip, который вы можете найти, если выполните текстовый поиск по http://d.hatena.ne.jp/punidama/20080227

Дайте мне знать, если вам нужны какие-то конкретные примеры для настройки этого.

...