7

私は、Java 経由で Wi​​ndows 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

これは、次の点を除いて、十分無害に思えます

  1. 「50」の音量は、プレーヤーの音量が実際に設定されている場所とは関係がなく、
  2. 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 コマンドを機能させる必要があります。やみくもに状態を切り替えるだけでは、開始時にプレーヤーがどの状態にあるかわからないため、役に立ちません。

私が間違っていること、または他に何を試すことができるかについて、誰かアドバイスはありますか?

4

2 に答える 2

2

それで、これらは機能しませんか?

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

(間違ったコードで申し訳ありません。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});

APPCOMMAND_MEDIA_PLAYXP SP1が必要ですが、それが展開されていると想定しています。

于 2009-04-21T15:21:15.080 に答える
1

wmpSettings を新しい ActiveXComponent としてインスタンス化すると、Jacob は、要求している設定プロパティを取得するのではなく、新しいメディア プレーヤー オブジェクトでコンポーネントをラップするために実際に面白いことをしているように見えます。

簡単に試しましたか:

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

また、ジェイコブを使用するようになった元の質問を読み返しました。これでホイールを長時間回転させた場合に備えて、別のアプローチを提案できます。

現在Webアプリケーションサーバーにログインしている特定のユーザーのデスクトップで、winampから実行されているshoutcastサーバーと対話するWebアプリケーションをセットアップしました。COM を使用して、Web アプリケーションのコンテキスト内から winamp のユーザーのインスタンスと直接通信することができなかったので、簡単な C# TCP/IP winamp ブリッジ アプリケーションをセットアップして、shoutcast ユーザーのデスクトップ上で実行し、Web アプリケーションがlocalhost からのソケット接続。

WMP の場合は、 http: //d.hatena.ne.jp/punidama/20080227 でテキスト検索を行うと、WmpRemote.zip のコードのような C# ラッパーを見つけることができると思います。

これを設定するための具体的な例が必要な場合はお知らせください。

于 2009-04-15T12:51:37.520 に答える