root/pjproject/trunk/pjsip-apps/src/py_pjsua/pjsua_app.py

Revision 1438, 21.1 kB (checked in by bennylp, 1 year ago)

Updated pjsua_app.py Python sample application to the new changes in Python module (thanks Gideon Klompje)

  • Property svn:eol-style set to native
  • Property svn:keywords set to id
Line 
1 # $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 #
8 import py_pjsua
9 import sys
10 import thread
11
12 #
13 # Configurations
14 #
15 THIS_FILE = "pjsua_app.py"
16 C_QUIT = 0
17 C_LOG_LEVEL = 4
18
19 # STUN config.
20 # Set C_STUN_HOST to the address:port of the STUN server to enable STUN
21 #
22 C_STUN_HOST = ""
23 #C_STUN_HOST = "192.168.0.2"
24 #C_STUN_HOST = "stun.iptel.org:3478"
25
26 # SIP port
27 C_SIP_PORT = 5060
28
29
30 # Globals
31 #
32 g_ua_cfg = None
33 g_acc_id = py_pjsua.PJSUA_INVALID_ID
34 g_current_call = py_pjsua.PJSUA_INVALID_ID
35 g_wav_files = []
36 g_wav_id = 0
37 g_wav_port = 0
38 g_rec_file = ""
39 g_rec_id = 0
40 g_rec_port = 0
41
42 # Utility: display PJ error and exit
43 #
44 def err_exit(title, rc):
45     py_pjsua.perror(THIS_FILE, title, rc)
46     py_pjsua.destroy()
47     exit(1)
48
49
50 # Logging function (also callback, called by pjsua-lib)
51 #
52 def log_cb(level, str, len):
53     if level <= C_LOG_LEVEL:
54         print str,
55
56 def write_log(level, str):
57     log_cb(level, str + "\n", 0)
58
59
60 # Utility to get call info
61 #
62 def call_name(call_id):
63         ci = py_pjsua.call_get_info(call_id)
64         return "[Call " + `call_id` + " " + ci.remote_info + "]"
65
66 # Callback when call state has changed.
67 #
68 def on_call_state(call_id, e): 
69         global g_current_call
70         ci = py_pjsua.call_get_info(call_id)
71         write_log(3, call_name(call_id) + " state = " + `ci.state_text`)
72         if ci.state == py_pjsua.PJSIP_INV_STATE_DISCONNECTED:
73                 g_current_call = py_pjsua.PJSUA_INVALID_ID
74
75 # Callback for incoming call
76 #
77 def on_incoming_call(acc_id, call_id, rdata):
78         global g_current_call
79        
80         if g_current_call != py_pjsua.PJSUA_INVALID_ID:
81                 # There's call in progress - answer Busy
82                 py_pjsua.call_answer(call_id, 486, None, None)
83                 return
84        
85         g_current_call = call_id
86         ci = py_pjsua.call_get_info(call_id)
87         write_log(3, "*** Incoming call: " + call_name(call_id) + "***")
88         write_log(3, "*** Press a to answer or h to hangup  ***")
89        
90        
91        
92 # Callback when media state has changed (e.g. established or terminated)
93 #
94 def on_call_media_state(call_id):
95         ci = py_pjsua.call_get_info(call_id)
96         if ci.media_status == py_pjsua.PJSUA_CALL_MEDIA_ACTIVE:
97                 py_pjsua.conf_connect(ci.conf_slot, 0)
98                 py_pjsua.conf_connect(0, ci.conf_slot)
99                 write_log(3, call_name(call_id) + ": media is active")
100         else:
101                 write_log(3, call_name(call_id) + ": media is inactive")
102
103
104 # Callback when account registration state has changed
105 #
106 def on_reg_state(acc_id):
107         acc_info = py_pjsua.acc_get_info(acc_id)
108         if acc_info.has_registration != 0:
109                 cmd = "registration"
110         else:
111                 cmd = "unregistration"
112         if acc_info.status != 0 and acc_info.status != 200:
113                 write_log(3, "Account " + cmd + " failed: rc=" + `acc_info.status` + " " + acc_info.status_text)
114         else:
115                 write_log(3, "Account " + cmd + " success")
116
117
118 # Callback when buddy's presence state has changed
119 #
120 def on_buddy_state(buddy_id):
121         write_log(3, "On Buddy state called")
122         buddy_info = py_pjsua.buddy_get_info(buddy_id)
123         if buddy_info.status != 0 and buddy_info.status != 200:
124                 write_log(3, "Status of " + `buddy_info.uri` + " is " + `buddy_info.status_text`)
125         else:
126                 write_log(3, "Status : " + `buddy_info.status`)
127
128 # Callback on incoming pager (MESSAGE)
129 #               
130 def on_pager(call_id, strfrom, strto, contact, mime_type, text):
131         write_log(3, "MESSAGE from " + `strfrom` + " : " + `text`)
132
133
134 # Callback on the delivery status of outgoing pager (MESSAGE)
135 #       
136 def on_pager_status(call_id, strto, body, user_data, status, reason):
137         write_log(3, "MESSAGE to " + `strto` + " status " + `status` + " reason " + `reason`)
138
139
140 # Received typing indication
141 #
142 def on_typing(call_id, strfrom, to, contact, is_typing):
143         str_t = ""
144         if is_typing:
145                 str_t = "is typing.."
146         else:
147                 str_t = "has stopped typing"
148         write_log(3, "IM indication: " + strfrom + " " + str_t)
149
150 # Received the status of previous call transfer request
151 #
152 def on_call_transfer_status(call_id,status_code,status_text,final,p_cont):
153         strfinal = ""
154         if final == 1:
155                 strfinal = "[final]"
156        
157         write_log(3, "Call " + `call_id` + ": transfer status= " + `status_code` + " " + status_text+ " " + strfinal)
158              
159         if status_code/100 == 2:
160                 write_log(3, "Call " + `call_id` + " : call transfered successfully, disconnecting call")
161                 status = py_pjsua.call_hangup(call_id, 410, None, None)
162                 p_cont = 0
163
164 # Callback on incoming call transfer request
165 #               
166 def on_call_transfer_request(call_id, dst, code):
167         write_log(3, "Call transfer request from " + `call_id` + " to " + dst + " with code " + `code`)
168
169 #
170 # Initialize pjsua.
171 #
172 def app_init():
173         global g_acc_id, g_ua_cfg
174
175         # Create pjsua before anything else
176         status = py_pjsua.create()
177         if status != 0:
178                 err_exit("pjsua create() error", status)
179
180         # Create and initialize logging config
181         log_cfg = py_pjsua.logging_config_default()
182         log_cfg.level = C_LOG_LEVEL
183         log_cfg.cb = log_cb
184
185         # Create and initialize pjsua config
186         # Note: for this Python module, thread_cnt must be 0 since Python
187         #       doesn't like to be called from alien thread (pjsua's thread
188         #       in this case)       
189         ua_cfg = py_pjsua.config_default()
190         ua_cfg.thread_cnt = 0
191         ua_cfg.user_agent = "PJSUA/Python 0.1"
192         ua_cfg.cb.on_incoming_call = on_incoming_call
193         ua_cfg.cb.on_call_media_state = on_call_media_state
194         ua_cfg.cb.on_reg_state = on_reg_state
195         ua_cfg.cb.on_call_state = on_call_state
196         ua_cfg.cb.on_buddy_state = on_buddy_state
197         ua_cfg.cb.on_pager = on_pager
198         ua_cfg.cb.on_pager_status = on_pager_status
199         ua_cfg.cb.on_typing = on_typing
200         ua_cfg.cb.on_call_transfer_status = on_call_transfer_status
201         ua_cfg.cb.on_call_transfer_request = on_call_transfer_request
202
203         # Configure STUN setting
204         if C_STUN_HOST != "":
205             ua_cfg.stun_host = C_STUN_HOST;
206
207         # Create and initialize media config
208         med_cfg = py_pjsua.media_config_default()
209         med_cfg.ec_tail_len = 0
210
211         #
212         # Initialize pjsua!!
213         #
214         status = py_pjsua.init(ua_cfg, log_cfg, med_cfg)
215         if status != 0:
216                 err_exit("pjsua init() error", status)
217
218         # Configure UDP transport config
219         transport_cfg = py_pjsua.transport_config_default()
220         transport_cfg.port = C_SIP_PORT
221
222         # Create UDP transport
223         status, transport_id = \
224             py_pjsua.transport_create(py_pjsua.PJSIP_TRANSPORT_UDP, transport_cfg)
225         if status != 0:
226                 err_exit("Error creating UDP transport", status)
227                
228
229         # Create initial default account
230         status, acc_id = py_pjsua.acc_add_local(transport_id, 1)
231         if status != 0:
232                 err_exit("Error creating account", status)
233
234         g_acc_id = acc_id
235         g_ua_cfg = ua_cfg
236
237 # Add SIP account interractively
238 #
239 def add_account():
240         global g_acc_id
241
242         acc_domain = ""
243         acc_username = ""
244         acc_passwd =""
245         confirm = ""
246        
247         # Input account configs
248         print "Your SIP domain (e.g. myprovider.com): ",
249         acc_domain = sys.stdin.readline()
250         if acc_domain == "\n":
251                 return
252         acc_domain = acc_domain.replace("\n", "")
253
254         print "Your username (e.g. alice): ",
255         acc_username = sys.stdin.readline()
256         if acc_username == "\n":
257                 return
258         acc_username = acc_username.replace("\n", "")
259
260         print "Your password (e.g. secret): ",
261         acc_passwd = sys.stdin.readline()
262         if acc_passwd == "\n":
263                 return
264         acc_passwd = acc_passwd.replace("\n", "")
265
266         # Configure account configuration
267         acc_cfg = py_pjsua.acc_config_default()
268         acc_cfg.id = "sip:" + acc_username + "@" + acc_domain
269         acc_cfg.reg_uri = "sip:" + acc_domain
270
271         cred_info = py_pjsua.Pjsip_Cred_Info()
272         cred_info.realm = "*"
273         cred_info.scheme = "digest"
274         cred_info.username = acc_username
275         cred_info.data_type = 0
276         cred_info.data = acc_passwd
277
278         acc_cfg.cred_info.append(1)
279         acc_cfg.cred_info[0] = cred_info
280
281         # Add new SIP account
282         status, acc_id = py_pjsua.acc_add(acc_cfg, 1)
283         if status != 0:
284                 py_pjsua.perror(THIS_FILE, "Error adding SIP account", status)
285         else:
286                 g_acc_id = acc_id
287                 write_log(3, "Account " + acc_cfg.id + " added")
288
289 def add_player():
290         global g_wav_files
291         global g_wav_id
292         global g_wav_port
293        
294         file_name = ""
295         status = -1
296         wav_id = 0
297        
298         print "Enter the path of the file player(e.g. /tmp/audio.wav): ",
299         file_name = sys.stdin.readline()
300         if file_name == "\n":
301                 return
302         file_name = file_name.replace("\n", "")
303         status, wav_id = py_pjsua.player_create(file_name, 0)
304         if status != 0:
305                 py_pjsua.perror(THIS_FILE, "Error adding file player ", status)
306         else:
307                 g_wav_files.append(file_name)
308                 if g_wav_id == 0:
309                         g_wav_id = wav_id
310                         g_wav_port = py_pjsua.player_get_conf_port(wav_id)
311                 write_log(3, "File player " + file_name + " added")
312                
313 def add_recorder():
314         global g_rec_file
315         global g_rec_id
316         global g_rec_port
317        
318         file_name = ""
319         status = -1
320         rec_id = 0
321        
322         print "Enter the path of the file recorder(e.g. /tmp/audio.wav): ",
323         file_name = sys.stdin.readline()
324         if file_name == "\n":
325                 return
326         file_name = file_name.replace("\n", "")
327         status, rec_id = py_pjsua.recorder_create(file_name, 0, None, 0, 0)
328         if status != 0:
329                 py_pjsua.perror(THIS_FILE, "Error adding file recorder ", status)
330         else:
331                 g_rec_file = file_name
332                 g_rec_id = rec_id
333                 g_rec_port = py_pjsua.recorder_get_conf_port(rec_id)
334                 write_log(3, "File recorder " + file_name + " added")
335
336 def conf_list():
337         ports = None
338         print "Conference ports : "
339         ports = py_pjsua.enum_conf_ports()
340
341         for port in ports:
342                 info = None
343                 info = py_pjsua.conf_get_port_info(port)
344                 txlist = ""
345                 for listener in info.listeners:
346                         txlist = txlist + "#" + `listener` + " "
347                
348                 print "Port #" + `info.slot_id` + "[" + `(info.clock_rate/1000)` + "KHz/" + `(info.samples_per_frame * 1000 / info.clock_rate)` + "ms] " + info.name + " transmitting to: " + txlist
349                
350 def connect_port():
351         src_port = 0
352         dst_port = 0
353        
354         print "Connect src port # (empty to cancel): "
355         src_port = sys.stdin.readline()
356         if src_port == "\n":
357                 return
358         src_port = src_port.replace("\n", "")
359         src_port = int(src_port)
360         print "To dst port # (empty to cancel): "
361         dst_port = sys.stdin.readline()
362         if dst_port == "\n":
363                 return
364         dst_port = dst_port.replace("\n", "")
365         dst_port = int(dst_port)
366         status = py_pjsua.conf_connect(src_port, dst_port)
367         if status != 0:
368                 py_pjsua.perror(THIS_FILE, "Error connecting port ", status)
369         else:           
370                 write_log(3, "Port connected from " + `src_port` + " to " + `dst_port`)
371                
372 def disconnect_port():
373         src_port = 0
374         dst_port = 0
375        
376         print "Disconnect src port # (empty to cancel): "
377         src_port = sys.stdin.readline()
378         if src_port == "\n":
379                 return
380         src_port = src_port.replace("\n", "")
381         src_port = int(src_port)
382         print "From dst port # (empty to cancel): "
383         dst_port = sys.stdin.readline()
384         if dst_port == "\n":
385                 return
386         dst_port = dst_port.replace("\n", "")
387         dst_port = int(dst_port)
388         status = py_pjsua.conf_disconnect(src_port, dst_port)
389         if status != 0:
390                 py_pjsua.perror(THIS_FILE, "Error disconnecting port ", status)
391         else:           
392                 write_log(3, "Port disconnected " + `src_port` + " from " + `dst_port`)
393
394 def dump_call_quality():
395         global g_current_call
396        
397         buf = ""
398         if g_current_call != -1:
399                 buf = py_pjsua.call_dump(g_current_call, 1, 1024, "  ")
400                 write_log(3, "\n" + buf)
401         else:
402                 write_log(3, "No current call")
403
404 def xfer_call():
405         global g_current_call
406        
407         if g_current_call == -1:
408                
409                 write_log(3, "No current call")
410
411         else:
412                 call = g_current_call           
413                 ci = py_pjsua.call_get_info(g_current_call)
414                 print "Transfering current call ["+ `g_current_call` + "] " + ci.remote_info
415                 print "Enter sip url : "
416                 url = sys.stdin.readline()
417                 if url == "\n":
418                         return
419                 url = url.replace("\n", "")
420                 if call != g_current_call:
421                         print "Call has been disconnected"
422                         return
423                 msg_data = py_pjsua.msg_data_init()
424                 status = py_pjsua.call_xfer(g_current_call, url, msg_data);
425                 if status != 0:
426                         py_pjsua.perror(THIS_FILE, "Error transfering call ", status)
427                 else:           
428                         write_log(3, "Call transfered to " + url)
429                
430 def xfer_call_replaces():
431         if g_current_call == -1:
432                 write_log(3, "No current call")
433         else:
434                 call = g_current_call
435                
436                 ids = py_pjsua.enum_calls()
437                 if len(ids) <= 1:
438                         print "There are no other calls"
439                         return         
440
441                 ci = py_pjsua.call_get_info(g_current_call)
442                 print "Transfer call [" + `g_current_call` + "] " + ci.remote_info + " to one of the following:"
443                 for i in range(0, len(ids)):               
444                         if ids[i] == call:
445                                 continue
446                         call_info = py_pjsua.call_get_info(ids[i])
447                         print `ids[i]` + "  " +  call_info.remote_info + "  [" + call_info.state_text + "]"             
448
449                 print "Enter call number to be replaced : "
450                 buf = sys.stdin.readline()
451                 buf = buf.replace("\n","")
452                 if buf == "":
453                         return
454                 dst_call = int(buf)
455                
456                 if call != g_current_call:
457                         print "Call has been disconnected"
458                         return         
459                
460                 if dst_call == call:
461                         print "Destination call number must not be the same as the call being transfered"
462                         return
463                
464                 if dst_call >= py_pjsua.PJSUA_MAX_CALLS:
465                         print "Invalid destination call number"
466                         return
467        
468                 if py_pjsua.call_is_active(dst_call) == 0:
469                         print "Invalid destination call number"
470                         return         
471
472                 py_pjsua.call_xfer_replaces(call, dst_call, 0, None)
473                
474 #
475 # Worker thread function.
476 # Python doesn't like it when it's called from an alien thread
477 # (pjsua's worker thread, in this case), so for Python we must
478 # disable worker thread in pjsua and poll pjsua from Python instead.
479 #
480 def worker_thread_main(arg):
481         global C_QUIT
482         thread_desc = 0;
483         status = py_pjsua.thread_register("python worker", thread_desc)
484         if status != 0:
485                 py_pjsua.perror(THIS_FILE, "Error registering thread", status)
486         else:
487                 while C_QUIT == 0:
488                         py_pjsua.handle_events(50)
489                 print "Worker thread quitting.."
490                 C_QUIT = 2
491
492
493 # Start pjsua
494 #
495 def app_start():
496         # Done with initialization, start pjsua!!
497         #
498         status = py_pjsua.start()
499         if status != 0:
500                 err_exit("Error starting pjsua!", status)
501
502         # Start worker thread
503         thr = thread.start_new(worker_thread_main, (0,))
504    
505         print "PJSUA Started!!"
506
507
508 # Print account and buddy list
509 def 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                
542 # Print application menu
543 #
544 def print_menu():
545         print ""
546         print ">>>"
547         print_acc_buddy_list()
548         print """
549 +============================================================================+
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  |
563 |                              | cc  Connect port         | dd  Dump detail  |
564 |                              | cd  Disconnect port      |                  |
565 |                              | +p  Add file player      |                  |
566 |------------------------------+ +r  Add file recorder    |                  |
567 |  q  Quit application         |                          |                  |
568 +============================================================================+"""
569         print "You have " + `py_pjsua.call_get_count()` + " active call(s)"
570         print ">>>",
571
572 # Menu
573 #
574 def app_menu():
575         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!
603                         py_pjsua.im_send(g_acc_id, url, None, message, None, 0)
604
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)
616            
617                         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            
630                         bc.uri = bc.uri.replace("\n", "")
631                         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)
635                 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"               
647                 elif choice[0] == "+" and choice[1] == "a":
648                         # Add account
649                         add_account()
650                 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)
657
658                         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()
680                 elif choice[0] == "h":
681                         if g_current_call != py_pjsua.PJSUA_INVALID_ID:
682                                 py_pjsua.call_hangup(g_current_call, 603, None, None)
683                         else:
684                                 print "No current call"
685                 elif choice[0] == "H":
686                         if g_current_call != py_pjsua.PJSUA_INVALID_ID:
687                                 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                         i