私は、Java 経由で Windows Media Player を制御することについて、しばらく前にここに質問した者です。 私は進歩しましたが、厄介な問題にぶつかったので、助けを求めて戻ってきました.
前回得たアドバイスに従い、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 の呼び出し後、プレーヤーの音量は実際には変化しません。
他のプロパティも試してみましたが同じです。プロパティの値はプレイヤーが実際に行っていることとは関係がないようで、プロパティを変更すると操作されるオブジェクトの状態が変化するように見えますが、実際のプレーヤーには影響しません。 (スクリプトを実行するたびにまったく同じ出力が得られるため、「ボリューム」をいじるときに変更しているものは何でも、コードの外部には永続性がありません。)
明らかに私は何か間違ったことをしていますが、何を理解しようとやみくもに手探りしています。何がうまくいかないのか、または次に何を試すべきなのかについて、誰かが私に洞察を提供できますか?
(注: 「WMPlayer.OCX」が正しい入力パラメータであるかどうかさえ確信が持てません。これが見つかるまで、レジストリの HKEY_CLASSES_ROOT にありそうなエントリを試してみました。)
誰かが提供できる助けを前もって感謝します。
編集、2009 年 4 月 15 日: EZ JCom という会社の製品の中に、WMP 固有のパッケージを見つけました。以前見たのとまったく同じ方法で失敗したため、Jacob の単なるラッパーであるか、WMP ActiveX/COM インターフェイスが明らかに壊れています。(待って、なぜ「どちらか」と言ったのですか?)
私はカスタマーサービスとチャットしました. 彼らは、動作中の WMP コードの例として提供された非コンパイル サンプル コードを修正するのを手伝ってくれましたが、ボリュームの取得/設定メソッドがどのように機能するかについての洞察を求めて彼らにせがんだところ、次のようになりました。
「申し訳ありませんが、ここでは WMP の詳細な専門知識を利用できません。EZ JCom は、Java と WMP などの他のプログラムとの間のブリッジ ビルダーにすぎません。」
私が評価していた彼らのパッケージは、実際には「wmp.WindowsMediaPlayer」と呼ばれていることに注意してください。もし私がそれを機能させていたら、私は上司にライセンスのために600ドルを払うように説得しなければならなかったでしょう. 彼らが実際に自社製品に関する専門知識を持っている場合、彼らは何を請求するのだろうか.
だから、本当の進歩はありません。共有したいと思っただけです。
編集、2009 年 4 月 20 日: ええ、私はまだこれを突っついています。私の現在の動作理論では、ボリューム設定を取得するには、リモートで WMP にアクセスする必要があるというものです。IWMPRemoteMediaServices および IServiceProvider インターフェイスについての言及を見てきましたが、後者の QueryService メソッドは前者へのポインターを提供します。残念ながら、IServiceProvider を取得する方法がわかりません。Windowsの「システム」オブジェクトからアクセスできるという言及を見てきましたが、そのオブジェクトを取得する方法がわかりません。(そして、「システム」という言葉は Java にかなり深く関わっているため、Google はノイズとシグナルの比率を非常に高く評価しています。) 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());
これにより、次の結果が得られます。
wmpハンドル: 1640048 ウィンドウ エラーを検索しますか? ヌル プレイ結果: -1 プレイエラー?ヌル 一時停止の結果: -1 一時停止エラー? ヌル
...しかし、実際にはメディアプレーヤーには影響しません。
APPCOMMAND_MEDIA_PLAY_PAUSE (14) でも試してみましたが、これは異なる戻り値 (20) を返しますが、何もしません。
FWIW、これを実行可能なオプションにするためには、個々の PLAY/PAUSE コマンドを機能させる必要があります。やみくもに状態を切り替えるだけでは、開始時にプレーヤーがどの状態にあるかわからないため、役に立ちません。
私が間違っていること、または他に何を試すことができるかについて、誰かアドバイスはありますか?