Programming a bird -- yes!

Hello all,

Hi all,

Serious (but possibly less attracting) subject title: Win32ole event loop
with MSAgent.

Thanks to Suketa Masaki for doing such a good job on giving us ‘win32ole’.
It relieves us from Microsoft’s RSI-stimulating clickfests.

···

Inspired by Rubytalk 36676, Shusaku tsyk@yk.rim.or.jp:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/36676

I decided I wanted to beef up my Agent-app with MSAgent (sorry, Unix):

http://www.microsoft.com/msagent/downloads/user.asp
(download merlin + speech engine + maybe more, depending on your
hardware)

Tried out the script below. All works fine — as a matter of fact, I
showed one of the characters who happens to be a bird called Peedy to my
4-year old son pronouncing my son’s name. He ran down to his mom and said
that a bird talked to him and knew his name :slight_smile:

Anyway:

#!/usr/bin/ruby
require ‘win32ole’

agent = WIN32OLE.new(‘Agent.Control.1’)
agent.Connected = true
agent.Characters.Load(“some random string, ‘peedy’ or so”, “peedy.acs”)

peedy = agent.Characters(“some random string, ‘peedy’ or so”)

The way we should officialy check when we’re done:

ev = WIN32OLE_EVENT.new(agent, nil)
ev.on_event(“RequestComplete”) { |rRequest|

rRequest.ole_obj_help.name -> “IAgentCtlRequest”

rRequest.ole_obj_help.typekind -> 4 ( TKIND_DISPATCH )

rRequest.ole_obj_help.ole_type -> “Dispatch”

rRequest.ID -> 197 ( ?? )

if rRequest.ID == $peedySpeak.ID
peedy.Hide # or exit, or move on, or …
end

}

peedy.Show

You can program gestures here. Nothing fancy at the moment, just

speak.

$peedySpeak = peedy.Speak <<EOF
Thanks Suketa Masaki, for giving us win32ole!
And thanks Shusaku, for giving us a link between Ruby-win32ole and
MsAgent!
EOF

speak = peedy.ole_method(“Speak”) #=> WIN32OLE_METHOD

speak.return_vtype #=> 26

speak.return_type #=> “IAgentCtlRequest”

speak.return_type_detail #=> [“PTR”, “USERDEFINED”, “IAgentCtlRequest”]

More mundane check to see when we’re done:

loop do
$stderr.puts $peedySpeak.Status
$stderr.flush

status should become 0 or so, see

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msagent/pacontrol_3tws.asp
break if $peedySpeak.Status != 2
sleep 1
end

never get here :frowning:

======================================================================

As you see, the WIN32OLE_EVENT-loop doesn’t seem to recognize events,
which is needed to recognize that an action is over.
Also, the “Status” attribute does not work. Status could also be used to
see that an action is over. Currently, Status keeps returning 2’s. This
is different from Perl’s,

foreach my $animation ($c->AnimationNames)
{
my $request = $c->Play($animation);
$c->Speak($animation);
my $i = 0;
while (($request->Status == 2) || ($request->Status == 4))
{ $c->Stop($request) if $i >10; sleep(1); $i++}
}

where it does* work (not the events, though). (Thanks, Jouke). See

http://www.cpan.org/modules/by-authors/id/J/JO/JOUKE/

Examined Suketa Masaki “ienavi.rb” example for inspiration. There must be
some “DWebBrowserEvents” event sink identifier for MSAgent as well, but
which??

Thanks.
Gerard

Interesting… I played with it for a couple of minutes and got it to work
as you indicated.

I downloaded the docs and there is a reference to a “Register” function. It
states that you must create a AgentNotifySink and register it before you can
get events. I’m not sure how to do this in Ruby. If you get it working,
please post the code.

Good luck.

···

-----Original Message-----
From: Gerard A.W. Vreeswijk [mailto:gv@cs.uu.nl]
Sent: July 14, 2003 7:10 AM
To: ruby-talk ML
Subject: programming a bird – yes!

Hello all,

Hi all,

Serious (but possibly less attracting) subject title: Win32ole event loop
with MSAgent.

Thanks to Suketa Masaki for doing such a good job on giving us ‘win32ole’.
It relieves us from Microsoft’s RSI-stimulating clickfests.

Inspired by Rubytalk 36676, Shusaku tsyk@yk.rim.or.jp:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/36676

I decided I wanted to beef up my Agent-app with MSAgent (sorry, Unix):

http://www.microsoft.com/msagent/downloads/user.asp
(download merlin + speech engine + maybe more, depending on your
hardware)

Tried out the script below. All works fine — as a matter of fact, I
showed one of the characters who happens to be a bird called Peedy to my
4-year old son pronouncing my son’s name. He ran down to his mom and said
that a bird talked to him and knew his name :slight_smile:

Anyway:

#!/usr/bin/ruby
require ‘win32ole’

agent = WIN32OLE.new(‘Agent.Control.1’)
agent.Connected = true
agent.Characters.Load(“some random string, ‘peedy’ or so”, “peedy.acs”)

peedy = agent.Characters(“some random string, ‘peedy’ or so”)

The way we should officialy check when we’re done:

ev = WIN32OLE_EVENT.new(agent, nil)
ev.on_event(“RequestComplete”) { |rRequest|

rRequest.ole_obj_help.name -> “IAgentCtlRequest”

rRequest.ole_obj_help.typekind -> 4 ( TKIND_DISPATCH )

rRequest.ole_obj_help.ole_type -> “Dispatch”

rRequest.ID -> 197 ( ?? )

if rRequest.ID == $peedySpeak.ID
peedy.Hide # or exit, or move on, or …
end

}

peedy.Show

You can program gestures here. Nothing fancy at the moment, just

speak.

$peedySpeak = peedy.Speak <<EOF
Thanks Suketa Masaki, for giving us win32ole!
And thanks Shusaku, for giving us a link between Ruby-win32ole and
MsAgent!
EOF

speak = peedy.ole_method(“Speak”) #=> WIN32OLE_METHOD

speak.return_vtype #=> 26

speak.return_type #=> “IAgentCtlRequest”

speak.return_type_detail #=> [“PTR”, “USERDEFINED”, “IAgentCtlRequest”]

More mundane check to see when we’re done:

loop do
$stderr.puts $peedySpeak.Status
$stderr.flush

status should become 0 or so, see

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msagent/pac
ontrol_3tws.asp
break if $peedySpeak.Status != 2
sleep 1
end

never get here :frowning:

======================================================================

As you see, the WIN32OLE_EVENT-loop doesn’t seem to recognize events,
which is needed to recognize that an action is over.
Also, the “Status” attribute does not work. Status could also be used to
see that an action is over. Currently, Status keeps returning 2’s. This
is different from Perl’s,

foreach my $animation ($c->AnimationNames)
{
my $request = $c->Play($animation);
$c->Speak($animation);
my $i = 0;
while (($request->Status == 2) || ($request->Status == 4))
{ $c->Stop($request) if $i >10; sleep(1); $i++}
}

where it does* work (not the events, though). (Thanks, Jouke). See

http://www.cpan.org/modules/by-authors/id/J/JO/JOUKE/

Examined Suketa Masaki “ienavi.rb” example for inspiration. There must be
some “DWebBrowserEvents” event sink identifier for MSAgent as well, but
which??

Thanks.
Gerard

Hi, Gerard

loop do
$stderr.puts $peedySpeak.Status
$stderr.flush
break if $peedySpeak.Status != 2
WIN32OLE_EVENT.message_loop # <== You should insert this!
sleep 1
end

Now, the loop would be terminated by ‘Status == 4’, although it
means “Request in progress”. I think the break condition might
be ‘Status == 0’, which means “Request successfully completed”.

···

On Mon, 14 Jul 2003 09:55:35 GMT gv@cs.uu.nl (Gerard A.W. Vreeswijk) wrote:


Shusaku tsyk@yk.rim.or.jp

Interesting… I played with it for a couple of minutes and got it to work
as you indicated.

I downloaded the docs and there is a reference to a “Register” function.

Ah, yes the docs. I waded for hours through them without success:
http://www.microsoft.com/msagent/dev/docs/default.asp#SDK

Hence the post :slight_smile:

It
states that you must create a AgentNotifySink and register it before you can
get events. I’m not sure how to do this in Ruby. If you get it working,
please post the code.

Sure do. (Although next couple of weeks I am travelling to la douce
France . . . . . . . without laptop :slight_smile:

Oh, while I’m at it. I’ve noticed that today always seems important to
the French. I’ll have to figure out why… :slight_smile:

···

On Mon, 14 Jul 2003 21:16:39 +0900, “Allen Mitchell” ajm@nb.sympatico.ca wrote:

I forgot to answer your other question.

···

On Mon, 14 Jul 2003 09:55:35 GMT gv@cs.uu.nl (Gerard A.W. Vreeswijk) wrote:

Examined Suketa Masaki “ienavi.rb” example for inspiration. There must be
some “DWebBrowserEvents” event sink identifier for MSAgent as well, but
which??

“_AgentEvents” is the one you are looking for.

agent = WIN32OLE.new(‘Agent.Control.1’)
ev = WIN32OLE_EVENT.new(agent, ‘_AgentEvents’)


Shusaku tsyk@yk.rim.or.jp