2009-04-14 7 views
7

Soy el tipo que estaba aquí hace un tiempo asking about controlling Windows Media Player via Java. He progresado, pero he tenido un problema complicado, así que estoy buscando ayuda.Reproductor de Windows Media ignorándome

Seguí el consejo que recibí la última vez e instalé a Jacob. Ejecuto estas líneas de un script de prueba:

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

... y WMP aparece, jugando SomaFM. "¡W00t!" Creo. "¡Tengo este resuelto!"

Excepto que cuando interactúo con este objeto después de su creación, parece que no tiene nada que ver con la reproducción de la instancia de WMP. Cuando ejecuto este código:

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")); 

... Puedo obtener una producción de:

 
VOLUME: 50 
VOLUME: 0 

Esto parece bastante inocuo, excepto que

  1. el volumen de "50" no tiene nada hacer con donde el volumen del jugador es realmente establecido y
  2. el volumen del jugador no realmente cambia después de la llamada setProperty.

he tratado también otras propiedades, pero es la misma cosa: no parece que el valor de las propiedades no estar relacionado con lo que el jugador está haciendo realidad, y mientras cambiarlas parece alterar el estado del objeto siendo manipulado, no tiene efecto sobre el jugador real . (Obtengo el mismo resultado cada vez que ejecuto el script, así que sea lo que sea lo que estoy alterando cuando doblo "volumen", no tiene persistencia fuera del código.)

Obviamente yo ' Estoy haciendo algo mal, pero estoy buscando a ciegas tratando de averiguar qué. ¿Alguien puede ofrecerme una idea de lo que está saliendo mal o de lo que debería intentar después?

(NOTA:.. Ni siquiera estoy seguro "WMPlayer.OCX" es el parámetro de entrada derecha Experimenté con entradas de aspecto probables en HKEY_CLASSES_ROOT en el registro hasta que encontré éste)

Mi agradecimiento en avance para cualquier ayuda que alguien pueda ofrecer.


Editar, 4/15/2009: he encontrado un paquete WMP-específico en las ofertas de una empresa llamada EZ Jcom. Falló de manera tan idéntica a lo que estaba viendo antes, o bien es solo un envoltorio para Jacob, o la interfaz WMP ActiveX/COM está completamente rota. (Espera, ¿por qué dije "cualquiera"?)

Conversé con el servicio al cliente, y terminaron demostrando cómo puedes ser útil sin ser realmente útil. Me ayudaron a corregir el código de ejemplo no compilado que proporcionaron como ejemplo de su código WMP en acción, pero cuando los fastidié para que me dieran una idea de cómo funcionan los métodos get/set volume, obtuve esto:

"Disculpe, pero no hay experiencia exhaustiva de WMP disponible aquí: EZ JCom es solo un generador de puentes entre Java y otros programas como WMP."

Tenga en cuenta que el paquete que estaba evaluando se llama realmente" wmp.WindowsMediaPlayer ". Si lo hubiera hecho funcionar, habría tenido que convencer a mi jefe para que pague $ 600 por la licencia. lo que habían cobrar si realmente tenían cierta experiencia en su propio producto

por lo tanto, hay un progreso real sólo pensé que sería buena idea compartir


Editar, 4/20/2009:... Sí, todavía estoy metiéndome en esto. Mi teoría operativa actual es que para acceder a la configuración del volumen, tendré que acceder al control remoto WMP. ly. He visto mencionar las interfaces IWMPRemoteMediaServices e IServiceProvider, y el método QueryService de este último proporciona un puntero al primero. Lamentablemente, no estoy teniendo suerte para averiguar cómo obtener IServiceProvider. He visto mencionar que es accesible desde el objeto "Sistema" de Windows, pero no puedo encontrar la manera de obtener ese objeto. (Y dado que la palabra "Sistema" figura bastante en Java, Google me está dando una relación de señal de ruido heráldico.) Si alguien tiene algún consejo sobre cómo pongo las manos sobre el objeto COM que representa System.dll, me encantaría oírlo.


Editar, 4/21/2009: Aclaración: esto es en un sistema XP.

También: mi investigación sugiere que simplemente hablar con el objeto WMP es insuficiente; necesitas envolverlo más apretadamente para que pueda responder. Hay un WMP SDK con muchas cosas en C++, pero parece depender de las extensiones de Microsoft Visual C++ para el código que no tengo y que no están regalando de forma gratuita. (Además, no he hecho C++ en doce años). Sé que es posible con C#, pero si estoy fuera de Java, necesitaría la solución para ser un ejecutable independiente y .NET no está instalado en las máquinas relevantes.


Editar, 4/22/2009: por la respuesta de la marca abajo, excavó el APPCOMMAND_MEDIA_ * constantes de winuser.h y trató el siguiente código, que hace uso de la API NativeCall:

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()); 

Esto me da un resultado de:

 
wmpHandle: 1640048 
Find Window Error? null 
Play Result: -1 
Play Error? null 
Pause Result: -1 
PauseError? null 

... pero no afecta realmente el reproductor multimedia.

También lo probé con APPCOMMAND_MEDIA_PLAY_PAUSE (14), que ofrece diferentes valores de retorno (20) pero tampoco hace nada.

FWIW, Realmente necesito que los comandos individuales PLAY/PAUSE funcionen para que esto sea una opción viable; simplemente alternar ciegamente el estado no me ayuda, ya que no sé en qué estado se encuentra el jugador cuando empiezo.

¿Alguien tiene algún consejo sobre lo que estoy haciendo mal o qué más puedo probar?

+0

Bueno, no tengo nada que decir en realidad para su problema solo quiero apoyarlo. – User

+1

Lo siento mucho, pareces muy frustrado y puedo entender por qué. Entonces desearía poder ayudar, pero no tengo experiencia en esto. Solo sentí que necesitaba darle un poco de apoyo moral, incluso si mi aporte en esto es virtualmente inútil. Espero que pases esto! –

+0

Mi agradecimiento a ambos; tu apoyo es apreciado :-) – BlairHippo

Respuesta

2

¿Entonces no funcionan?

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

(Disculpas por un código incorrecto, nunca he usado antes de Jacob)


En ese caso, crear/find cualquier ventana y send que APPCOMMAND_MEDIA_PLAY_PAUSE. El procesamiento de mensajes predeterminado lo afectará a WMP. (Enviar silencio no sirve, ya que eso silenciará todo el sistema.)

Para la portabilidad, recomendaría crear una utilidad de línea de comandos C++ o usar JNI, pero NativeCall podría ser suficiente por ahora.


Su código se ve bien, pero creo que solo necesita cambiar los parámetros a SendMessage. Proveedores:

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

APPCOMMAND_MEDIA_PLAY requiere XP SP1, pero estoy suponiendo que tiene que desplegarse.

+0

Lo deseo sinceramente. :-) Lamentablemente no. Investigaciones adicionales han insinuado que, básicamente, cuando tratas de hablar con WMP de esta manera, te va a hacer preguntas, y si no le gusta lo que tienes que decir, te ignorará. (Lo cual es consistente con mi experiencia.) Ejecutar esos comandos es como jugar con un volante de juguete conectado a una caja de arena; puedes girarlo todo lo que quieras, pero nada está sucediendo realmente. – BlairHippo

+0

Sí, probablemente necesite implementar IWMPRemoteMediaServices, lo que supongo que Jacob no puede hacer. – Mark

+0

¡Gracias! Este es un enfoque que no había considerado antes, pero desafortunadamente todavía no funciona. Por favor, mira la publicación editada arriba y avísame si tienes alguna idea de cómo estoy jodiéndolo. – BlairHippo

1

Parece que al instanciar wmpSettings como un nuevo ActiveXComponent, Jacob está haciendo algo divertido para envolver el componente en un nuevo objeto de reproductor multimedia en lugar de recuperar la propiedad de configuración que está solicitando.

Ha intentado simplemente:

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

También fui atrás y leer la pregunta original que se metió en el uso de Jacob y lo que puedo sugerir un enfoque diferente en el caso de que terminan haciendo girar las ruedas en esto durante demasiado largo.

Había configurado una aplicación web que interactuaba con un servidor shoutcast que se ejecutaba desde winamp en el escritorio de un usuario específico que estaba actualmente conectado al servidor de la aplicación web. No pude usar COM para comunicarme directamente con la instancia de winamp del usuario desde el contexto de la aplicación web, así que configuré una sencilla aplicación de puente winamp C# TCP/IP que se ejecutaba en el escritorio del usuario de shoutcast y permitía que la aplicación web creara un conexión de socket desde localhost.

para WMP estoy seguro de que puede encontrar algunos envoltorios de C# como el código para WmpRemote.zip se pueden encontrar si usted hace una búsqueda de texto en http://d.hatena.ne.jp/punidama/20080227

Déjeme saber si usted necesita ningún ejemplo específico para establecer este arriba.

+0

Hola, gracias por los comentarios. El código que sugiere no compila (no existe tal como Dispatch.setProperty()), pero sí lo hace: "Dispatch.put (wmpSettings," volume ", 0);" Produce exactamente el mismo comportamiento que antes, lamentablemente – BlairHippo

+0

¿Conoces alguna de esas envolturas de C# que se han compilado para ejecutarse como aplicaciones independientes? Implementar .NET en todas las máquinas que necesitarían ejecutar esto no es una opción. (Reconozco que no sé mucho sobre C# /. NET, así que mis disculpas si esa es una pregunta estúpida. :-)) – BlairHippo

Cuestiones relacionadas