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!