blob: 7dca31b3f8b39767f7a9610c58d3ddb347719e71 [file] [log] [blame]
Benny Prijonoaa286042007-02-03 17:23:22 +00001# $Id$
2#
3# Sample and simple Python script to make and receive calls, and do
4# presence and instant messaging/IM using PJSUA-API binding for Python.
5#
6# Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
7#
Benny Prijonodc308702006-12-09 00:39:42 +00008import py_pjsua
9import sys
10import thread
11
12#
13# Configurations
14#
Benny Prijonoed7a5a72007-01-29 18:36:38 +000015THIS_FILE = "pjsua_app.py"
Benny Prijonodc308702006-12-09 00:39:42 +000016C_QUIT = 0
Benny Prijonoed7a5a72007-01-29 18:36:38 +000017C_LOG_LEVEL = 4
Benny Prijonodc308702006-12-09 00:39:42 +000018
Benny Prijonoed7a5a72007-01-29 18:36:38 +000019# STUN config.
20# Set C_STUN_SRV to the address of the STUN server to enable STUN
21#
Benny Prijonodc308702006-12-09 00:39:42 +000022C_STUN_SRV = ""
Benny Prijonoed7a5a72007-01-29 18:36:38 +000023C_SIP_PORT = 5060
Benny Prijonodc308702006-12-09 00:39:42 +000024C_STUN_PORT = 3478
25
Benny Prijonodc308702006-12-09 00:39:42 +000026
Benny Prijonoed7a5a72007-01-29 18:36:38 +000027# Globals
28#
Fahris89ea3d02007-02-07 08:18:35 +000029g_ua_cfg = None
Benny Prijonoed7a5a72007-01-29 18:36:38 +000030g_acc_id = py_pjsua.PJSUA_INVALID_ID
31g_current_call = py_pjsua.PJSUA_INVALID_ID
Fahris89ea3d02007-02-07 08:18:35 +000032g_wav_files = []
33g_wav_id = 0
34g_wav_port = 0
35g_rec_file = ""
36g_rec_id = 0
37g_rec_port = 0
Benny Prijonoed7a5a72007-01-29 18:36:38 +000038
Benny Prijonoda275f62007-02-18 23:49:14 +000039# Utility: display PJ error and exit
40#
41def err_exit(title, rc):
42 py_pjsua.perror(THIS_FILE, title, rc)
43 exit(1)
44
45
46# Logging function (also callback, called by pjsua-lib)
47#
48def log_cb(level, str, len):
49 if level <= C_LOG_LEVEL:
50 print str,
51
52def write_log(level, str):
53 log_cb(level, str + "\n", 0)
54
55
Benny Prijonoed7a5a72007-01-29 18:36:38 +000056# Utility to get call info
57#
58def call_name(call_id):
59 ci = py_pjsua.call_get_info(call_id)
60 return "[Call " + `call_id` + " " + ci.remote_info + "]"
61
Benny Prijonoaa286042007-02-03 17:23:22 +000062# Callback when call state has changed.
Benny Prijonoed7a5a72007-01-29 18:36:38 +000063#
64def on_call_state(call_id, e):
65 global g_current_call
66 ci = py_pjsua.call_get_info(call_id)
67 write_log(3, call_name(call_id) + " state = " + `ci.state_text`)
Benny Prijonoaa286042007-02-03 17:23:22 +000068 if ci.state == py_pjsua.PJSIP_INV_STATE_DISCONNECTED:
Benny Prijonoed7a5a72007-01-29 18:36:38 +000069 g_current_call = py_pjsua.PJSUA_INVALID_ID
70
Benny Prijonoaa286042007-02-03 17:23:22 +000071# Callback for incoming call
Benny Prijonoed7a5a72007-01-29 18:36:38 +000072#
73def on_incoming_call(acc_id, call_id, rdata):
74 global g_current_call
Fahris89ea3d02007-02-07 08:18:35 +000075
Benny Prijonoed7a5a72007-01-29 18:36:38 +000076 if g_current_call != py_pjsua.PJSUA_INVALID_ID:
Benny Prijonoaa286042007-02-03 17:23:22 +000077 # There's call in progress - answer Busy
78 py_pjsua.call_answer(call_id, 486, None, None)
Benny Prijonoed7a5a72007-01-29 18:36:38 +000079 return
Fahris89ea3d02007-02-07 08:18:35 +000080
Benny Prijonoed7a5a72007-01-29 18:36:38 +000081 g_current_call = call_id
82 ci = py_pjsua.call_get_info(call_id)
Benny Prijonoaa286042007-02-03 17:23:22 +000083 write_log(3, "*** Incoming call: " + call_name(call_id) + "***")
Fahris89ea3d02007-02-07 08:18:35 +000084 write_log(3, "*** Press a to answer or h to hangup ***")
85
86
Benny Prijonoed7a5a72007-01-29 18:36:38 +000087
Benny Prijonoaa286042007-02-03 17:23:22 +000088# Callback when media state has changed (e.g. established or terminated)
Benny Prijonoed7a5a72007-01-29 18:36:38 +000089#
90def on_call_media_state(call_id):
91 ci = py_pjsua.call_get_info(call_id)
Benny Prijonoaa286042007-02-03 17:23:22 +000092 if ci.media_status == py_pjsua.PJSUA_CALL_MEDIA_ACTIVE:
Benny Prijonoed7a5a72007-01-29 18:36:38 +000093 py_pjsua.conf_connect(ci.conf_slot, 0)
94 py_pjsua.conf_connect(0, ci.conf_slot)
95 write_log(3, call_name(call_id) + ": media is active")
96 else:
97 write_log(3, call_name(call_id) + ": media is inactive")
98
99
Benny Prijonoaa286042007-02-03 17:23:22 +0000100# Callback when account registration state has changed
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000101#
102def on_reg_state(acc_id):
103 acc_info = py_pjsua.acc_get_info(acc_id)
Benny Prijonoda275f62007-02-18 23:49:14 +0000104 if acc_info.has_registration != 0:
105 cmd = "registration"
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000106 else:
Benny Prijonoda275f62007-02-18 23:49:14 +0000107 cmd = "unregistration"
108 if acc_info.status != 0 and acc_info.status != 200:
109 write_log(3, "Account " + cmd + " failed: rc=" + `acc_info.status` + " " + acc_info.status_text)
110 else:
111 write_log(3, "Account " + cmd + " success")
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000112
113
Benny Prijonoaa286042007-02-03 17:23:22 +0000114# Callback when buddy's presence state has changed
115#
Fahrise314b882007-02-02 10:52:04 +0000116def on_buddy_state(buddy_id):
117 write_log(3, "On Buddy state called")
118 buddy_info = py_pjsua.buddy_get_info(buddy_id)
119 if buddy_info.status != 0 and buddy_info.status != 200:
120 write_log(3, "Status of " + `buddy_info.uri` + " is " + `buddy_info.status_text`)
121 else:
122 write_log(3, "Status : " + `buddy_info.status`)
Benny Prijonoaa286042007-02-03 17:23:22 +0000123
124# Callback on incoming pager (MESSAGE)
125#
Fahrise314b882007-02-02 10:52:04 +0000126def on_pager(call_id, strfrom, strto, contact, mime_type, text):
127 write_log(3, "MESSAGE from " + `strfrom` + " : " + `text`)
Benny Prijonoaa286042007-02-03 17:23:22 +0000128
129
130# Callback on the delivery status of outgoing pager (MESSAGE)
131#
Fahrise314b882007-02-02 10:52:04 +0000132def on_pager_status(call_id, strto, body, user_data, status, reason):
133 write_log(3, "MESSAGE to " + `strto` + " status " + `status` + " reason " + `reason`)
134
Benny Prijonoaa286042007-02-03 17:23:22 +0000135
Fahris89ea3d02007-02-07 08:18:35 +0000136# Received typing indication
137#
138def on_typing(call_id, strfrom, to, contact, is_typing):
139 str_t = ""
140 if is_typing:
141 str_t = "is typing.."
142 else:
143 str_t = "has stopped typing"
144 write_log(3, "IM indication: " + strfrom + " " + str_t)
145
Benny Prijonoda275f62007-02-18 23:49:14 +0000146# Received the status of previous call transfer request
Fahris89ea3d02007-02-07 08:18:35 +0000147#
148def on_call_transfer_status(call_id,status_code,status_text,final,p_cont):
149 strfinal = ""
150 if final == 1:
151 strfinal = "[final]"
152
153 write_log(3, "Call " + `call_id` + ": transfer status= " + `status_code` + " " + status_text+ " " + strfinal)
154
155 if status_code/100 == 2:
156 write_log(3, "Call " + `call_id` + " : call transfered successfully, disconnecting call")
157 status = py_pjsua.call_hangup(call_id, 410, None, None)
158 p_cont = 0
159
Benny Prijonoda275f62007-02-18 23:49:14 +0000160# Callback on incoming call transfer request
Fahris89ea3d02007-02-07 08:18:35 +0000161#
162def on_call_transfer_request(call_id, dst, code):
163 write_log(3, "Call transfer request from " + `call_id` + " to " + dst + " with code " + `code`)
164
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000165#
166# Initialize pjsua.
167#
Benny Prijonodc308702006-12-09 00:39:42 +0000168def app_init():
Fahris89ea3d02007-02-07 08:18:35 +0000169 global g_acc_id, g_ua_cfg
Benny Prijonodc308702006-12-09 00:39:42 +0000170
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000171 # Create pjsua before anything else
172 status = py_pjsua.create()
173 if status != 0:
174 err_exit("pjsua create() error", status)
Benny Prijonodc308702006-12-09 00:39:42 +0000175
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000176 # Create and initialize logging config
177 log_cfg = py_pjsua.logging_config_default()
178 log_cfg.level = C_LOG_LEVEL
179 log_cfg.cb = log_cb
Benny Prijonodc308702006-12-09 00:39:42 +0000180
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000181 # Create and initialize pjsua config
182 # Note: for this Python module, thread_cnt must be 0 since Python
183 # doesn't like to be called from alien thread (pjsua's thread
184 # in this case)
185 ua_cfg = py_pjsua.config_default()
186 ua_cfg.thread_cnt = 0
187 ua_cfg.user_agent = "PJSUA/Python 0.1"
188 ua_cfg.cb.on_incoming_call = on_incoming_call
189 ua_cfg.cb.on_call_media_state = on_call_media_state
190 ua_cfg.cb.on_reg_state = on_reg_state
191 ua_cfg.cb.on_call_state = on_call_state
Fahrise314b882007-02-02 10:52:04 +0000192 ua_cfg.cb.on_buddy_state = on_buddy_state
193 ua_cfg.cb.on_pager = on_pager
194 ua_cfg.cb.on_pager_status = on_pager_status
Fahris89ea3d02007-02-07 08:18:35 +0000195 ua_cfg.cb.on_typing = on_typing
196 ua_cfg.cb.on_call_transfer_status = on_call_transfer_status
197 ua_cfg.cb.on_call_transfer_request = on_call_transfer_request
Benny Prijonodc308702006-12-09 00:39:42 +0000198
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000199 # Create and initialize media config
200 med_cfg = py_pjsua.media_config_default()
201 med_cfg.ec_tail_len = 0
Benny Prijonodc308702006-12-09 00:39:42 +0000202
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000203 #
204 # Initialize pjsua!!
205 #
206 status = py_pjsua.init(ua_cfg, log_cfg, med_cfg)
207 if status != 0:
208 err_exit("pjsua init() error", status)
Benny Prijonodc308702006-12-09 00:39:42 +0000209
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000210 # Configure STUN config
Benny Prijonofbec9972007-04-02 16:56:20 +0000211 #stun_cfg = py_pjsua.stun_config_default()
212 #stun_cfg.stun_srv1 = C_STUN_SRV
213 #stun_cfg.stun_srv2 = C_STUN_SRV
214 #stun_cfg.stun_port1 = C_STUN_PORT
215 #stun_cfg.stun_port2 = C_STUN_PORT
Benny Prijonodc308702006-12-09 00:39:42 +0000216
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000217 # Configure UDP transport config
218 transport_cfg = py_pjsua.transport_config_default()
219 transport_cfg.port = C_SIP_PORT
Benny Prijonofbec9972007-04-02 16:56:20 +0000220 #transport_cfg.stun_config = stun_cfg
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000221 if C_STUN_SRV != "":
222 transport_cfg.use_stun = 1
223
224 # Create UDP transport
Benny Prijonoaa286042007-02-03 17:23:22 +0000225 status, transport_id = \
226 py_pjsua.transport_create(py_pjsua.PJSIP_TRANSPORT_UDP, transport_cfg)
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000227 if status != 0:
228 py_pjsua.destroy()
229 err_exit("Error creating UDP transport", status)
230
231 # Create initial default account
232 status, acc_id = py_pjsua.acc_add_local(transport_id, 1)
233 if status != 0:
234 py_pjsua.destroy()
235 err_exit("Error creating account", status)
236
237 g_acc_id = acc_id
Fahris89ea3d02007-02-07 08:18:35 +0000238 g_ua_cfg = ua_cfg
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000239
240# Add SIP account interractively
241#
242def add_account():
243 global g_acc_id
244
245 acc_domain = ""
246 acc_username = ""
247 acc_passwd =""
248 confirm = ""
249
250 # Input account configs
251 print "Your SIP domain (e.g. myprovider.com): ",
252 acc_domain = sys.stdin.readline()
253 if acc_domain == "\n":
254 return
255 acc_domain = acc_domain.replace("\n", "")
256
257 print "Your username (e.g. alice): ",
258 acc_username = sys.stdin.readline()
259 if acc_username == "\n":
260 return
261 acc_username = acc_username.replace("\n", "")
262
263 print "Your password (e.g. secret): ",
264 acc_passwd = sys.stdin.readline()
265 if acc_passwd == "\n":
266 return
267 acc_passwd = acc_passwd.replace("\n", "")
268
269 # Configure account configuration
270 acc_cfg = py_pjsua.acc_config_default()
271 acc_cfg.id = "sip:" + acc_username + "@" + acc_domain
272 acc_cfg.reg_uri = "sip:" + acc_domain
273 acc_cfg.cred_count = 1
274 acc_cfg.cred_info[0].realm = acc_domain
275 acc_cfg.cred_info[0].scheme = "digest"
276 acc_cfg.cred_info[0].username = acc_username
277 acc_cfg.cred_info[0].data_type = 0
278 acc_cfg.cred_info[0].data = acc_passwd
279
280 # Add new SIP account
281 status, acc_id = py_pjsua.acc_add(acc_cfg, 1)
282 if status != 0:
283 py_pjsua.perror(THIS_FILE, "Error adding SIP account", status)
284 else:
285 g_acc_id = acc_id
286 write_log(3, "Account " + acc_cfg.id + " added")
Benny Prijonodc308702006-12-09 00:39:42 +0000287
Fahris89ea3d02007-02-07 08:18:35 +0000288def add_player():
289 global g_wav_files
290 global g_wav_id
291 global g_wav_port
292
293 file_name = ""
294 status = -1
295 wav_id = 0
296
297 print "Enter the path of the file player(e.g. /tmp/audio.wav): ",
298 file_name = sys.stdin.readline()
299 if file_name == "\n":
300 return
301 file_name = file_name.replace("\n", "")
302 status, wav_id = py_pjsua.player_create(file_name, 0)
303 if status != 0:
304 py_pjsua.perror(THIS_FILE, "Error adding file player ", status)
305 else:
306 g_wav_files.append(file_name)
307 if g_wav_id == 0:
308 g_wav_id = wav_id
309 g_wav_port = py_pjsua.player_get_conf_port(wav_id)
310 write_log(3, "File player " + file_name + " added")
311
312def add_recorder():
313 global g_rec_file
314 global g_rec_id
315 global g_rec_port
316
317 file_name = ""
318 status = -1
319 rec_id = 0
320
321 print "Enter the path of the file recorder(e.g. /tmp/audio.wav): ",
322 file_name = sys.stdin.readline()
323 if file_name == "\n":
324 return
325 file_name = file_name.replace("\n", "")
326 status, rec_id = py_pjsua.recorder_create(file_name, 0, None, 0, 0)
327 if status != 0:
328 py_pjsua.perror(THIS_FILE, "Error adding file recorder ", status)
329 else:
330 g_rec_file = file_name
331 g_rec_id = rec_id
332 g_rec_port = py_pjsua.recorder_get_conf_port(rec_id)
333 write_log(3, "File recorder " + file_name + " added")
Benny Prijonodc308702006-12-09 00:39:42 +0000334
Fahris89ea3d02007-02-07 08:18:35 +0000335def conf_list():
Fahris89ea3d02007-02-07 08:18:35 +0000336 ports = None
Fahris89ea3d02007-02-07 08:18:35 +0000337 print "Conference ports : "
Fahris89ea3d02007-02-07 08:18:35 +0000338 ports = py_pjsua.enum_conf_ports()
339
340 for port in ports:
341 info = None
342 info = py_pjsua.conf_get_port_info(port)
343 txlist = ""
344 for i in range(info.listener_cnt):
345 txlist = txlist + "#" + `info.listeners[i]` + " "
346
347 print "Port #" + `info.slot_id` + "[" + `(info.clock_rate/1000)` + "KHz/" + `(info.samples_per_frame * 1000 / info.clock_rate)` + "ms] " + info.name + " transmitting to: " + txlist
348
349def connect_port():
350 src_port = 0
351 dst_port = 0
352
353 print "Connect src port # (empty to cancel): "
354 src_port = sys.stdin.readline()
355 if src_port == "\n":
356 return
357 src_port = src_port.replace("\n", "")
358 src_port = int(src_port)
359 print "To dst port # (empty to cancel): "
360 dst_port = sys.stdin.readline()
361 if dst_port == "\n":
362 return
363 dst_port = dst_port.replace("\n", "")
364 dst_port = int(dst_port)
365 status = py_pjsua.conf_connect(src_port, dst_port)
366 if status != 0:
367 py_pjsua.perror(THIS_FILE, "Error connecting port ", status)
368 else:
369 write_log(3, "Port connected from " + `src_port` + " to " + `dst_port`)
370
371def disconnect_port():
372 src_port = 0
373 dst_port = 0
374
375 print "Disconnect src port # (empty to cancel): "
376 src_port = sys.stdin.readline()
377 if src_port == "\n":
378 return
379 src_port = src_port.replace("\n", "")
380 src_port = int(src_port)
381 print "From dst port # (empty to cancel): "
382 dst_port = sys.stdin.readline()
383 if dst_port == "\n":
384 return
385 dst_port = dst_port.replace("\n", "")
386 dst_port = int(dst_port)
387 status = py_pjsua.conf_disconnect(src_port, dst_port)
388 if status != 0:
389 py_pjsua.perror(THIS_FILE, "Error disconnecting port ", status)
390 else:
391 write_log(3, "Port disconnected " + `src_port` + " from " + `dst_port`)
392
393def dump_call_quality():
394 global g_current_call
395
396 buf = ""
397 if g_current_call != -1:
398 buf = py_pjsua.call_dump(g_current_call, 1, 1024, " ")
399 write_log(3, "\n" + buf)
400 else:
401 write_log(3, "No current call")
Benny Prijonoda275f62007-02-18 23:49:14 +0000402
Fahris89ea3d02007-02-07 08:18:35 +0000403def xfer_call():
404 global g_current_call
405
406 if g_current_call == -1:
407
408 write_log(3, "No current call")
409
410 else:
411 call = g_current_call
412 ci = py_pjsua.call_get_info(g_current_call)
413 print "Transfering current call ["+ `g_current_call` + "] " + ci.remote_info
414 print "Enter sip url : "
415 url = sys.stdin.readline()
416 if url == "\n":
417 return
418 url = url.replace("\n", "")
419 if call != g_current_call:
420 print "Call has been disconnected"
421 return
422 msg_data = py_pjsua.msg_data_init()
423 status = py_pjsua.call_xfer(g_current_call, url, msg_data);
424 if status != 0:
425 py_pjsua.perror(THIS_FILE, "Error transfering call ", status)
426 else:
427 write_log(3, "Call transfered to " + url)
428
429def xfer_call_replaces():
430 if g_current_call == -1:
431 write_log(3, "No current call")
432 else:
433 call = g_current_call
434
435 ids = py_pjsua.enum_calls()
436 if len(ids) <= 1:
437 print "There are no other calls"
438 return
439
440 ci = py_pjsua.call_get_info(g_current_call)
441 print "Transfer call [" + `g_current_call` + "] " + ci.remote_info + " to one of the following:"
442 for i in range(0, len(ids)):
443 if ids[i] == call:
444 continue
445 call_info = py_pjsua.call_get_info(ids[i])
446 print `ids[i]` + " " + call_info.remote_info + " [" + call_info.state_text + "]"
447
448 print "Enter call number to be replaced : "
449 buf = sys.stdin.readline()
450 buf = buf.replace("\n","")
451 if buf == "":
452 return
453 dst_call = int(buf)
454
455 if call != g_current_call:
456 print "Call has been disconnected"
457 return
458
459 if dst_call == call:
460 print "Destination call number must not be the same as the call being transfered"
461 return
462
463 if dst_call >= py_pjsua.PJSUA_MAX_CALLS:
464 print "Invalid destination call number"
465 return
466
467 if py_pjsua.call_is_active(dst_call) == 0:
468 print "Invalid destination call number"
469 return
470
471 py_pjsua.call_xfer_replaces(call, dst_call, 0, None)
472
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000473#
474# Worker thread function.
475# Python doesn't like it when it's called from an alien thread
476# (pjsua's worker thread, in this case), so for Python we must
477# disable worker thread in pjsua and poll pjsua from Python instead.
478#
Benny Prijonodc308702006-12-09 00:39:42 +0000479def worker_thread_main(arg):
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000480 global C_QUIT
481 thread_desc = 0;
482 status = py_pjsua.thread_register("python worker", thread_desc)
483 if status != 0:
484 py_pjsua.perror(THIS_FILE, "Error registering thread", status)
485 else:
486 while C_QUIT == 0:
487 py_pjsua.handle_events(50)
488 print "Worker thread quitting.."
489 C_QUIT = 2
490
Benny Prijonodc308702006-12-09 00:39:42 +0000491
492# Start pjsua
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000493#
Benny Prijonodc308702006-12-09 00:39:42 +0000494def app_start():
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000495 # Done with initialization, start pjsua!!
496 #
497 status = py_pjsua.start()
498 if status != 0:
499 py_pjsua.destroy()
500 err_exit("Error starting pjsua!", status)
Benny Prijonodc308702006-12-09 00:39:42 +0000501
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000502 # Start worker thread
503 thr = thread.start_new(worker_thread_main, (0,))
Benny Prijonodc308702006-12-09 00:39:42 +0000504
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000505 print "PJSUA Started!!"
Benny Prijonodc308702006-12-09 00:39:42 +0000506
507
Benny Prijonoda275f62007-02-18 23:49:14 +0000508# Print account and buddy list
509def print_acc_buddy_list():
510 global g_acc_id
511
512 acc_ids = py_pjsua.enum_accs()
513 print "Account list:"
514 for acc_id in acc_ids:
515 acc_info = py_pjsua.acc_get_info(acc_id)
516 if acc_info.has_registration == 0:
517 acc_status = acc_info.status_text
518 else:
519 acc_status = `acc_info.status` + "/" + acc_info.status_text + " (expires=" + `acc_info.expires` + ")"
520
521 if acc_id == g_acc_id:
522 print " *",
523 else:
524 print " ",
525
526 print "[" + `acc_id` + "] " + acc_info.acc_uri + ": " + acc_status
527 print " Presence status: ",
528 if acc_info.online_status != 0:
529 print "Online"
530 else:
531 print "Invisible"
532
533 if py_pjsua.get_buddy_count() > 0:
534 print ""
535 print "Buddy list:"
536 buddy_ids = py_pjsua.enum_buddies()
537 for buddy_id in buddy_ids:
538 bi = py_pjsua.buddy_get_info(buddy_id)
539 print " [" + `buddy_id` + "] " + bi.status_text + " " + bi.uri
540
541
Benny Prijonodc308702006-12-09 00:39:42 +0000542# Print application menu
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000543#
Benny Prijonodc308702006-12-09 00:39:42 +0000544def print_menu():
Benny Prijonoda275f62007-02-18 23:49:14 +0000545 print ""
546 print ">>>"
547 print_acc_buddy_list()
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000548 print """
Fahris89ea3d02007-02-07 08:18:35 +0000549+============================================================================+
550| Call Commands : | Buddy, IM & Presence: | Account: |
551| | | |
552| m Make call | +b Add buddy | +a Add account |
553| a Answer current call | -b Delete buddy | -a Delete accnt |
554| h Hangup current call | | |
555| H Hold call | i Send instant message | rr register |
556| v re-inVite (release Hold) | s Subscribe presence | ru Unregister |
557| # Send DTMF string | u Unsubscribe presence | |
558| dq Dump curr. call quality | t ToGgle Online status | |
559| +--------------------------+------------------+
560| x Xfer call | Media Commands: | Status: |
561| X Xfer with Replaces | | |
562| | cl List ports | d Dump status |
Benny Prijonoda275f62007-02-18 23:49:14 +0000563| | cc Connect port | dd Dump detail |
Fahris89ea3d02007-02-07 08:18:35 +0000564| | cd Disconnect port | |
565| | +p Add file player | |
566|------------------------------+ +r Add file recorder | |
567| q Quit application | | |
Benny Prijonoda275f62007-02-18 23:49:14 +0000568+============================================================================+"""
569 print "You have " + `py_pjsua.call_get_count()` + " active call(s)"
570 print ">>>",
Benny Prijonodc308702006-12-09 00:39:42 +0000571
Benny Prijonodc308702006-12-09 00:39:42 +0000572# Menu
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000573#
Benny Prijonodc308702006-12-09 00:39:42 +0000574def app_menu():
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000575 global g_acc_id
576 global g_current_call
577
578 quit = 0
579 while quit == 0:
580 print_menu()
581 choice = sys.stdin.readline()
582
583 if choice[0] == "q":
584 quit = 1
585
586 elif choice[0] == "i":
587 # Sending IM
588 print "Send IM to SIP URL: ",
589 url = sys.stdin.readline()
590 if url == "\n":
591 continue
592
593 # Send typing indication
594 py_pjsua.im_typing(g_acc_id, url, 1, None)
595
596 print "The content: ",
597 message = sys.stdin.readline()
598 if message == "\n":
599 py_pjsua.im_typing(g_acc_id, url, 0, None)
600 continue
601
602 # Send the IM!
Benny Prijonoaa286042007-02-03 17:23:22 +0000603 py_pjsua.im_send(g_acc_id, url, None, message, None, 0)
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000604
605 elif choice[0] == "m":
606 # Make call
607 print "Using account ", g_acc_id
608 print "Make call to SIP URL: ",
609 url = sys.stdin.readline()
610 url = url.replace("\n", "")
611 if url == "":
612 continue
613
614 # Initiate the call!
615 status, call_id = py_pjsua.call_make_call(g_acc_id, url, 0, 0, None)
Benny Prijonodc308702006-12-09 00:39:42 +0000616
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000617 if status != 0:
618 py_pjsua.perror(THIS_FILE, "Error making call", status)
619 else:
620 g_current_call = call_id
621
622 elif choice[0] == "+" and choice[1] == "b":
623 # Add new buddy
624 bc = py_pjsua.Buddy_Config()
625 print "Buddy URL: ",
626 bc.uri = sys.stdin.readline()
627 if bc.uri == "\n":
628 continue
629
Benny Prijonoda275f62007-02-18 23:49:14 +0000630 bc.uri = bc.uri.replace("\n", "")
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000631 bc.subscribe = 1
632 status, buddy_id = py_pjsua.buddy_add(bc)
633 if status != 0:
634 py_pjsua.perror(THIS_FILE, "Error adding buddy", status)
Fahris89ea3d02007-02-07 08:18:35 +0000635 elif choice[0] == "-" and choice[1] == "b":
636 print "Enter buddy ID to delete : "
637 buf = sys.stdin.readline()
638 buf = buf.replace("\n","")
639 if buf == "":
640 continue
641 i = int(buf)
642 if py_pjsua.buddy_is_valid(i) == 0:
643 print "Invalid buddy id " + `i`
644 else:
645 py_pjsua.buddy_del(i)
646 print "Buddy " + `i` + " deleted"
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000647 elif choice[0] == "+" and choice[1] == "a":
648 # Add account
649 add_account()
Fahris89ea3d02007-02-07 08:18:35 +0000650 elif choice[0] == "-" and choice[1] == "a":
651 print "Enter account ID to delete : "
652 buf = sys.stdin.readline()
653 buf = buf.replace("\n","")
654 if buf == "":
655 continue
656 i = int(buf)
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000657
Fahris89ea3d02007-02-07 08:18:35 +0000658 if py_pjsua.acc_is_valid(i) == 0:
659 print "Invalid account id " + `i`
660 else:
661 py_pjsua.acc_del(i)
662 print "Account " + `i` + " deleted"
663
664 elif choice[0] == "+" and choice[1] == "p":
665 add_player()
666 elif choice[0] == "+" and choice[1] == "r":
667 add_recorder()
668 elif choice[0] == "c" and choice[1] == "l":
669 conf_list()
670 elif choice[0] == "c" and choice[1] == "c":
671 connect_port()
672 elif choice[0] == "c" and choice[1] == "d":
673 disconnect_port()
674 elif choice[0] == "d" and choice[1] == "q":
675 dump_call_quality()
676 elif choice[0] == "x":
677 xfer_call()
678 elif choice[0] == "X":
679 xfer_call_replaces()
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000680 elif choice[0] == "h":
681 if g_current_call != py_pjsua.PJSUA_INVALID_ID:
Benny Prijonoaa286042007-02-03 17:23:22 +0000682 py_pjsua.call_hangup(g_current_call, 603, None, None)
683 else:
684 print "No current call"
Fahris89ea3d02007-02-07 08:18:35 +0000685 elif choice[0] == "H":
Benny Prijonoaa286042007-02-03 17:23:22 +0000686 if g_current_call != py_pjsua.PJSUA_INVALID_ID:
Fahris89ea3d02007-02-07 08:18:35 +0000687 py_pjsua.call_set_hold(g_current_call, None)
688
689 else:
690 print "No current call"
691 elif choice[0] == "v":
692 if g_current_call != py_pjsua.PJSUA_INVALID_ID:
693
694 py_pjsua.call_reinvite(g_current_call, 1, None);
695
696 else:
697 print "No current call"
698 elif choice[0] == "#":
699 if g_current_call == py_pjsua.PJSUA_INVALID_ID:
700 print "No current call"
701 elif py_pjsua.call_has_media(g_current_call) == 0:
702 print "Media is not established yet!"
703 else:
704 call = g_current_call
705 print "DTMF strings to send (0-9*#A-B)"
706 buf = sys.stdin.readline()
707 buf = buf.replace("\n", "")
708 if buf == "":
709 continue
710 if call != g_current_call:
711 print "Call has been disconnected"
712 continue
713 status = py_pjsua.call_dial_dtmf(g_current_call, buf)
714 if status != 0:
715 py_pjsua.perror(THIS_FILE, "Unable to send DTMF", status);
716 else:
717 print "DTMF digits enqueued for transmission"
718 elif choice[0] == "s":
719 print "Subscribe presence of (buddy id) : "
720 buf = sys.stdin.readline()
721 buf = buf.replace("\n","")
722 if buf == "":
723 continue
724 i = int(buf)
725 py_pjsua.buddy_subscribe_pres(i, 1)
726 elif choice[0] == "u":
727 print "Unsubscribe presence of (buddy id) : "
728 buf = sys.stdin.readline()
729 buf = buf.replace("\n","")
730 if buf == "":
731 continue
732 i = int(buf)
733 py_pjsua.buddy_subscribe_pres(i, 0)
734 elif choice[0] == "t":
735 acc_info = py_pjsua.acc_get_info(g_acc_id)
736 if acc_info.online_status == 0:
737 acc_info.online_status = 1
738 else:
739 acc_info.online_status = 0
740 py_pjsua.acc_set_online_status(g_acc_id, acc_info.online_status)
741 st = ""
742 if acc_info.online_status == 0:
743 st = "offline"
744 else:
745 st = "online"
746 print "Setting " + acc_info.acc_uri + " online status to " + st
747 elif choice[0] == "r":
748 if choice[1] == "r":
749 py_pjsua.acc_set_registration(g_acc_id, 1)
750 elif choice[1] == "u":
751 py_pjsua.acc_set_registration(g_acc_id, 0)
752 elif choice[0] == "d":
Benny Prijonoda275f62007-02-18 23:49:14 +0000753 py_pjsua.dump(choice[1] == "d")
Fahris89ea3d02007-02-07 08:18:35 +0000754 elif choice[0] == "a":
755 if g_current_call != py_pjsua.PJSUA_INVALID_ID:
756
Benny Prijonoaa286042007-02-03 17:23:22 +0000757 py_pjsua.call_answer(g_current_call, 200, None, None)
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000758 else:
759 print "No current call"
Benny Prijonodc308702006-12-09 00:39:42 +0000760
761
762#
763# main
764#
765app_init()
766app_start()
767app_menu()
768
769#
770# Done, quitting..
771#
772print "PJSUA shutting down.."
773C_QUIT = 1
Benny Prijonoed7a5a72007-01-29 18:36:38 +0000774# Give the worker thread chance to quit itself
775while C_QUIT != 2:
776 py_pjsua.handle_events(50)
777
778print "PJSUA destroying.."
Benny Prijonodc308702006-12-09 00:39:42 +0000779py_pjsua.destroy()
780