AutoHotkey Community

It is currently May 26th, 2012, 8:27 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: August 19th, 2009, 10:34 am 
Offline

Joined: June 20th, 2009, 10:03 pm
Posts: 13
I've had a lot of success using the Skype client provided by Buddy on this thread: http://www.autohotkey.com/forum/topic36712.html. This client essentially provides the ability to send a Skype phone messages (such as "call someone") and has a message handler that allows me to do things like send DTMF tones once I know the call has been set up properly.

One thing I've had trouble doing well is trying to build scripts that wait for a message to be received (or for a timeout to occur), before doing something else. In a threaded environment I'd use some type of thread synchronization mechanism like a mutex. In autohotkey I've been trying to use SetTimer but I'm almost certain that I'm not really doing it right.

As an example, I've tried to set up a little script that will send a PING to the Skype phone and let me know if the communication is working (if my message handler gets the PONG message), or not (if I time out). To do this I wrote the following:

Code:
; Test that the script is able to connect to the Skype Client
+#T::
TestSkypeConnection:
  SkypeMessage := "#ahk PING"
  writeAPI(SkypeMessage)
  WaitCount := 0
  PongReceived := "false"
  While (WaitCount < 100) {
    SetTimer WaitForPong, 250
    WaitCount += 1
  }
return

WaitForPong:
  if (WaitCount > 40) {
    SetTimer, WaitForPong, Off
   WaitCount := 200         ;break out of the loop above
   if (PongReceived != "false") {
     MsgBox Print Instructions Here at some point. 
   } else {
      MsgBox, 1, , "Timed out trying to connect to Skype Client.  Try Again?"
      IfMsgBox OK
   GoTo, TestSkypeConnection
      else
        return
   }
  }
return


This "kind of" works, but it feels kludgy and it doesn't generally time out properly. The whole idea of having to put the loops and the counters around the SetTimer call and the Label handler seems wrong, but it was the only way I got the handler to be called periodically, so I could check if my message arrived or if my counter had exceeded a limit.

Can anyone point me to a good tutorial on how I should really be using SetTimer (or another thread synchronization method?)

For completeness, here is a bare bones message handler just so you can see what is going on there:
Code:
SkypeReceive(wParam, lParam) {
    global
    ;---------------------------------------------------------------------------
    ; This is the address of CopyDataStruct's lpData member
    ;---------------------------------------------------------------------------
    lpDataAddress := lParam + 8  ; .
    lpData := 0
    ;---------------------------------------------------------------------------
    ; For each byte in the lpData integer
    ;---------------------------------------------------------------------------
    Loop 4  ; For each byte in the lpData integer
    {
        ;---------------------------------------------------------------------------
        ; Build the integer from its bytes
        ;---------------------------------------------------------------------------
        lpData := lpData | (*lpDataAddress << 8 * (A_Index - 1))
        ;---------------------------------------------------------------------------
        ; Move on to the next byte
        ;---------------------------------------------------------------------------
        lpDataAddress += 1
    }

    ;---------------------------------------------------------------------------
    ; lpData contains the address of the string to be copied
    ; (must be a zero-terminated string)
    ;---------------------------------------------------------------------------
    DataLength := DllCall("lstrlen", UInt, lpData)
    If DataLength <= 0
        msgbox blank received
    Else
    {
        VarSetCapacity(textReceived, DataLength)
        DllCall("lstrcpy", "str", textReceived, "uint", lpData)  ; Copy the string out of the structure.
        ;msgbox % textReceived
        If InStr(textReceived, "RINGING") {
            SkypeCallID := StringMod(textReceived, "Only", "0123456789")
        } Else If (InStr(textReceived, "PONG") && InStr(textReceived, "#ahk")) {
       ;Bump up the wait counter so we'll break out of the loop waiting for call setup
       WaitCount := 111
      PongReceived := "true"
        } ; else ignore the message
    }
    Return true
}


Thanks for any advice!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 19th, 2009, 11:01 am 
Offline

Joined: May 12th, 2008, 2:23 pm
Posts: 30
Location: Germany
skype has a com api. use it instead. link. much easier, and much prettier code.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 20th, 2009, 2:10 am 
Thanks Thrawn.

I'm sure that the com api may be more elegant, but I'm using this primarily as an example of a problem I'm more generally interested in solving.

In AHK, what is the best way to "cede control" to the system and wait for an external event (ie: a button press or a message from another process), while still having the ability to check back periodically in order to implement a timeout?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 20th, 2009, 6:13 am 
Offline

Joined: July 6th, 2009, 9:58 pm
Posts: 678
Anonymous wrote:
Thanks Thrawn.

I'm sure that the com api may be more elegant, but I'm using this primarily as an example of a problem I'm more generally interested in solving.

In AHK, what is the best way to "cede control" to the system and wait for an external event (ie: a button press or a message from another process), while still having the ability to check back periodically in order to implement a timeout?


Use GetKeyState in a loop?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 20th, 2009, 8:23 am 
Offline
User avatar

Joined: August 30th, 2005, 8:43 pm
Posts: 8666
Location: Salem, MA
Should this topic be moved to Ask for help?

It's both a useful code snippet, and at the same time a question.

_________________
Image
(Common Answers) - New Tutorials Forum - Humongous FAQ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 21st, 2009, 3:11 am 
Offline

Joined: June 26th, 2006, 6:14 pm
Posts: 1379
Location: USA
try this test script..not tested...
Code:
+#T::
TestSkypeConnection:
  SkypeMessage := "#ahk PING"
  writeAPI(SkypeMessage)
  WaitCount := 0
  PongReceived := false
WaitCount := 0
PongReceived := false
NumberOfTimesToTry := 10
While (WaitCount < NumberOfTimesToTry) {
   if (PongReceived) {
      MsgBox Pong has been received
      Break
   } else {
      WaitCount += 1
      Sleep, 100
;      Continue
   }
   if (WaitCount = NumberOfTimesToTry) {
      MsgBox, 1, , Timed out trying to connect to Skype Client.  Try Again?
      IfMsgBox OK
         WaitCount = 0
      else
         break
   }
;   MsgBox % WaitCount
}
MsgBox, Done
Return

_________________
Image
ʞɔпɟ əɥʇ ʇɐɥʍ


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Exabot [Bot], Google Feedfetcher, notsoobvious and 16 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group