エージェントについて・・

解決


エージェントォゥ!!  2005-10-05 20:34:50  No: 17898

お世話になりっぱなしですみません。

Speak で連続して文字列を送信すると
おしゃべりが終了するのに時間がかかるのですが、
処理はとまることなく実行されていきます。

おしゃべりが終了するのをまってから、
次の処理へと移動したいのですが、
どうすればよいのでしょうか?


ぶちょう  2005-10-05 21:16:26  No: 17899

英語の言語使用では
以下のようにしなさいと使い方が説明してあります。

procedure TForm1.hoge;
var
  A : IAgentCtlRequest;
begin
  A := FCharacter.Speak('hoge','');
  FCharacter.Wait(A);
//次の処理
end;

しかーし、なぜかDelphiでは動きません。

そこで、TAgentには「RequestComplete」というイベントが
あるので、このイベントが発生するまでは次の処理をさせない
といった管理をしてやるとうまく出来ます。
このイベントは、話したり動いたりが終わったら発生します。


ぶちょう  2005-10-05 21:18:51  No: 17900

誤字すいません(w
>英語の言語使用では
英語の言語仕様ですね。
ちなみにVBでの使い方として紹介されていました。


エージェントォゥ!!  2005-10-05 22:19:13  No: 17901

ぶちょうさんどうもお世話になります。
早速ですが、ためしてみました。

AgentRequestStart  も  AgentRequestComplete
のどちらも、イベントが発生しないんですが・・・

それから、別もんですみませんが、
Connected プロパティって
一度 True にすると False に戻りませんが、
このプロパティって何でしょうか?


エージェントォゥ!!  2005-10-05 22:37:51  No: 17902

ちなみにイベントは以下のようにしました。
RequestProcess: Boolean; をグローバルにして

procedure TFormMain.AgentRequestStart(Sender: TObject;
  const Request: IDispatch);
begin
  RequestProcess := True
end;

procedure TFormMain.AgentRequestComplete(Sender: TObject;
  const Request: IDispatch);
begin
  RequestProcess := False;
end;

呼び出し部分はこんな感じです。

Character.Show(False);
Character.Speak('メッセージ1', '');
Character.Speak('メッセージ2', '');
                      :
Character.Speak('メッセージn', '');
while RequestPRocess do Application.ProcessMessages;
//  処理
//  この部分では別メニューを表示して音声を出すが、
//  以下のHide が途中で実行され、キャラが引っ込んでしまう・・・
//
Character.Hide(false);


ぶちょう  2005-10-05 22:46:45  No: 17903

意味不明かも知れませんけど、下のように一行追加してみてください。

>呼び出し部分はこんな感じです。

>Character.Show(False);
>Character.Speak('メッセージ1', '');
>Character.Speak('メッセージ2', '');
RequestPRocess := True;←この場所に、これをつけてみてください。
>Character.Speak('メッセージn', '');
>while RequestPRocess do Application.ProcessMessages;
>//  処理
>//  この部分では別メニューを表示して音声を出すが、
>//  以下のHide が途中で実行され、キャラが引っ込んでしまう・・・
>//
>Character.Hide(false);


エージェントォゥ!!  2005-10-05 23:16:06  No: 17904

もっと簡単なテストプロ作ってみました。
しゃべり始める前に、ShowMessage  が実行されます。
Delphi6 を使用しています。

  Character.Show(False);
  RequestProcess := True;
  Character.Speak('メッセージ', '');
  //  しゃべり終わるまで待つ
  while MSWSystem.RequestProcess  do Application.ProcessMessages;
  if RequestProcess
    then ShowMessage('しゃべり終わった = True')
    else ShowMessage('しゃべり終わった = False');
  Character.Hide(False);


エージェントォゥ!!  2005-10-05 23:17:16  No: 17905

while RequestProcess  do Application.ProcessMessages

間違っていたので修正しました。
結果は同じです。


ぶちょう  2005-10-05 23:31:24  No: 17906

おかしいですね、イベント発生しないですか・・
どうも、フォームが2つ以上あるみたいなので、お手数ですが
いったん新しくプロジェクトを作成して試してみてください。

フォームに、ボタンとTAgentだけを貼り付けて、
グローバルにFFlg:booleanを作って、以下のコードで。 

procedure TForm1.Button1Click(Sender: TObject);
begin
  Agent.Characters.Load('MyChara','C:\WINDOWS\MSAGENT\CHARS\Genie.acs');//ここは環境にあわせて
  Character := Agent.Characters.Character('MyChara')as IAgentCtlCharacterEx;
  Character.Show(False);
  FFlg := True;
  Character.Speak('こんにちは', '');
  
  while FFlg do Application.ProcessMessages;
  Character.Speak('こんにちは', '');
  Character.Hide(False);
end;

procedure TForm1.AgentRequestComplete(ASender: TObject;
  const Request: IDispatch);
begin
  FFlg := False;
  Button1.Caption := datetimetostr(now);//反映されたか確認を
end;

procedure TForm1.AgentRequestStart(ASender: TObject;
  const Request: IDispatch);
begin
  FFlg := True;
end;

xpでDel7と2005しかないですが、こっちでは発生します。。


エージェントォゥ!!  2005-10-05 23:57:33  No: 17907

ぶちょうさん  すみません。
なんらかの状態のときに発生しないことがあるようです。
いじってるうちに動くようになりました。
でも、発生しなかった状態にすることはできませんでした。

show, Speak, while, hide で、  
while の入れる位置によって違うようなというより、
while 上記の問題で 別処理に移動して、そこでまた、
音声処理しているのでその辺が怪しいのかと・・・

サンプルで試したときはイベント発生は確かにしています。
ただ、問題は、前記のとおり、
イベントがすぐに発生し、て  False になって
while 文をすぐに抜けてしまいます。
どうしてなんでしょうか?


ぶちょう  2005-10-06 00:08:45  No: 17908

先ほどから、めっちゃ気になっているのが

MSWSystem.RequestProcessの「MSWSystem」なのですが、
MSWSystemとは別フォームですか?これは何者ですか?

MSWSystemにもRequestProcessがあり、
メインルーチンが動いているフォームにもRequestProcess
があったりとか・・・しませんよね?
・・・まさかですよね。いや、失礼。

うーん、なぜでしょう。もっと判断材料があれば。。

ちなみに、イベント発生条件についてですが先のサンプルで書いた
>  Character.Show(False);
>  FFlg := True;
>  Character.Speak('こんにちは', '');
の FFlg := True;の箇所をコメントアウトすると発生しなくなります。
これについてですが、私も意味不明です。Delphiが最適化してる?


エージェントォゥ!!  2005-10-06 01:58:04  No: 17909

MSWSystem は TObject から派生したクラスで・・・
アプリケーション内で使用している
グローバル変数や、関数をひとまとめにしたものです。
どうしてこんなことしてるかというと。
支援機能を使ったときに
[MSWSystem.]で変数名や、関数名の参照が出るためです。
そうすると[MSWSystem]だけ覚えておけばあとの共通で使用する関数や
変数といったものは支援機能のリストで表示されるからで、
VCLとかのクラスからの派生じゃありません。

MSWSystem.pas (基本ユニット)を作成しグローバル部で
---------------------------------
var
 MSWSystem: TMSWSystem;
---------------------------------
と記述して、後は、MSWSystem を使用するユニット(すべてのユニット)に
Uses で追加指定して使用しています。

前置きが長くなりましたが、本題にはいります。
以下は現在のテストプログラムです
●ステップ実行で1行ずつ実行していくと3種類の音量になると思います。
●次に普通に実行します。そうするとPCにより違うかもしれませんが
  メッセージ1とメッセージ2は同じ音量で、
  メッセージ3は音がでません。
●イベント部分にブレークポイントを入れると停止します。
  イベントは発生しています。

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtrls, AgentObjects_TLB, StdCtrls, MMSystem;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Agent1: TAgent;
    procedure Button1Click(Sender: TObject);
    procedure Agent1RequestComplete(Sender: TObject; const Request: IDispatch);
    procedure FormCreate(Sender: TObject);
  private
    Character:  IAgentCtlCharacterEx;
    RequestPRocess:  Boolean;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Agent1.Characters.Load('MyChara', 'C:\Windows\MSAGENT\CHARS\Peedy.acs');
  Character := Agent1.Characters.Character('MyChara') as IAgentCtlCharacterEx;
  Character.Set_TTSModeID('{A778E061-A936-11d1-B17B-0020AFED142E}');
  Character.LanguageID := $0411;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Character.Show(False);

  WaveOutSetVolume(0, $40404040);
  RequestPRocess := True;
  Character.Speak('メッセージ1', '');
  while RequestPRocess do Application.ProcessMessages;

  WaveOutSetVolume(0, $80808080);
  RequestPRocess := True;
  Character.Speak('メッセージ2', '');
  while RequestPRocess do Application.ProcessMessages;

  WaveOutSetVolume(0, $FFFFFFFF);
  RequestPRocess := True;
  Character.Speak('メッセージ3', '');
  while RequestPRocess do Application.ProcessMessages;

  WaveOutSetVolume(0, 0);

  Character.Hide(False);
end;

procedure TForm1.Agent1RequestComplete(Sender: TObject; const Request: IDispatch);
begin
  RequestPRocess := False;
end;

end.


エージェントォゥ!!  2005-10-06 02:06:32  No: 17910

ボタンを押したときの処理を
以下のようにすると3種類の音量で聞けるのですが、
鳥さんが行ったりきたりしてしまうので、
これじゃ使用できないですよね。

もし、このアニメの表示をオフにできる方法があれば
行ったりきたりしないですむのですが、
そういった方法は・・??
と、思ったのですが、もしあったとしても、
アニメ表示がないとShow や、 Hide もなくなるわけですよね....

−−−−−−−−−−−−−−−−−−−−−−−−−−
  Character.Show(False);
  WaveOutSetVolume(0, $40404040);
  Character.Speak('メッセージ1', '');
  Character.Hide(False);
  while Character.Visible do Application.ProcessMessages;

  Character.Show(False);
  WaveOutSetVolume(0, $80808080);
  Character.Speak('メッセージ2', '');
  Character.Hide(False);
  while Character.Visible do Application.ProcessMessages;

  Character.Show(False);
  WaveOutSetVolume(0, $FFFFFFFF);
  Character.Speak('メッセージ3', '');
  Character.Hide(False);
  while Character.Visible do Application.ProcessMessages;

  WaveOutSetVolume(0, 0);


ぶちょう  2005-10-06 02:23:13  No: 17911

試しに、
グローバルに
    ACR : IAgentCtlRequest;
と宣言して、

それぞれのSpeakをコールしている所を
ACR := Character.Speak('メッセージ?', '');
に変更して、

Agent1RequestCompleteを次のように変更したらどうでしょう?
procedure TForm1.Agent1RequestComplete(Sender: TObject; const Request: IDispatch);
begin
  if ACR <> Request then Exit;
  RequestPRocess := False;
end;


エージェントォゥ!!  2005-10-06 03:13:31  No: 17912

ぶちょう さん、
音量が3種類になり目的通りの処理ができました!

どうして?
いまひとつ理解できてません。


ぶちょう  2005-10-06 03:36:38  No: 17913

おー。よかったですね。

Speak以外にもリクエストがどこかで発行されていて、
それのコンプリートイベントを受信してしまっているからでしょうね。

エージェントが内部的にリクエストを発行しているのかも
しれませんし。


エージェントォゥ!!  2005-10-06 05:15:20  No: 17914

ぶちょうさん  お手数をおかけして
どうもありがとうございました。

なんとかなりそうです。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加