⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pjsua_app.py

📁 一个开源SIP协议栈
💻 PY
📖 第 1 页 / 共 2 页
字号:
# $Id: pjsua_app.py 972 2007-02-18 23:49:14Z bennylp $
#
# Sample and simple Python script to make and receive calls, and do
# presence and instant messaging/IM using PJSUA-API binding for Python.
#
# Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
#
import py_pjsua
import sys
import thread

#
# Configurations
#
THIS_FILE = "pjsua_app.py"
C_QUIT = 0
C_LOG_LEVEL = 4

# STUN config.
# Set C_STUN_SRV to the address of the STUN server to enable STUN
#
C_STUN_SRV = ""
C_SIP_PORT = 5060
C_STUN_PORT = 3478


# Globals
#
g_ua_cfg = None
g_acc_id = py_pjsua.PJSUA_INVALID_ID
g_current_call = py_pjsua.PJSUA_INVALID_ID
g_wav_files = []
g_wav_id = 0
g_wav_port = 0
g_rec_file = ""
g_rec_id = 0
g_rec_port = 0

# Utility: display PJ error and exit
#
def err_exit(title, rc):
    py_pjsua.perror(THIS_FILE, title, rc)
    exit(1)


# Logging function (also callback, called by pjsua-lib)
#
def log_cb(level, str, len):
    if level <= C_LOG_LEVEL:
        print str,

def write_log(level, str):
    log_cb(level, str + "\n", 0)


# Utility to get call info
#
def call_name(call_id):
	ci = py_pjsua.call_get_info(call_id)
	return "[Call " + `call_id` + " " + ci.remote_info + "]"

# Callback when call state has changed.
#
def on_call_state(call_id, e):	
	global g_current_call
	ci = py_pjsua.call_get_info(call_id)
	write_log(3, call_name(call_id) + " state = " + `ci.state_text`)
	if ci.state == py_pjsua.PJSIP_INV_STATE_DISCONNECTED:
		g_current_call = py_pjsua.PJSUA_INVALID_ID

# Callback for incoming call
#
def on_incoming_call(acc_id, call_id, rdata):
	global g_current_call
	
	if g_current_call != py_pjsua.PJSUA_INVALID_ID:
		# There's call in progress - answer Busy
		py_pjsua.call_answer(call_id, 486, None, None)
		return
	
	g_current_call = call_id
	ci = py_pjsua.call_get_info(call_id)
	write_log(3, "*** Incoming call: " + call_name(call_id) + "***")
	write_log(3, "*** Press a to answer or h to hangup  ***")
	
	
	
# Callback when media state has changed (e.g. established or terminated)
#
def on_call_media_state(call_id):
	ci = py_pjsua.call_get_info(call_id)
	if ci.media_status == py_pjsua.PJSUA_CALL_MEDIA_ACTIVE:
		py_pjsua.conf_connect(ci.conf_slot, 0)
		py_pjsua.conf_connect(0, ci.conf_slot)
		write_log(3, call_name(call_id) + ": media is active")
	else:
		write_log(3, call_name(call_id) + ": media is inactive")


# Callback when account registration state has changed
#
def on_reg_state(acc_id):
	acc_info = py_pjsua.acc_get_info(acc_id)
	if acc_info.has_registration != 0:
		cmd = "registration"
	else:
		cmd = "unregistration"
	if acc_info.status != 0 and acc_info.status != 200:
		write_log(3, "Account " + cmd + " failed: rc=" + `acc_info.status` + " " + acc_info.status_text)
	else:
		write_log(3, "Account " + cmd + " success")


# Callback when buddy's presence state has changed
#
def on_buddy_state(buddy_id):
	write_log(3, "On Buddy state called")
	buddy_info = py_pjsua.buddy_get_info(buddy_id)
	if buddy_info.status != 0 and buddy_info.status != 200:
		write_log(3, "Status of " + `buddy_info.uri` + " is " + `buddy_info.status_text`)
	else:
		write_log(3, "Status : " + `buddy_info.status`)

# Callback on incoming pager (MESSAGE)
#		
def on_pager(call_id, strfrom, strto, contact, mime_type, text):
	write_log(3, "MESSAGE from " + `strfrom` + " : " + `text`)


# Callback on the delivery status of outgoing pager (MESSAGE)
#	
def on_pager_status(call_id, strto, body, user_data, status, reason):
	write_log(3, "MESSAGE to " + `strto` + " status " + `status` + " reason " + `reason`)


# Received typing indication
#
def on_typing(call_id, strfrom, to, contact, is_typing):
	str_t = ""
	if is_typing:
		str_t = "is typing.."
	else:
		str_t = "has stopped typing"
	write_log(3, "IM indication: " + strfrom + " " + str_t)

# Received the status of previous call transfer request
#
def on_call_transfer_status(call_id,status_code,status_text,final,p_cont):
	strfinal = ""
	if final == 1:
		strfinal = "[final]"
	
	write_log(3, "Call " + `call_id` + ": transfer status= " + `status_code` + " " + status_text+ " " + strfinal)
	      
	if status_code/100 == 2:
		write_log(3, "Call " + `call_id` + " : call transfered successfully, disconnecting call")
		status = py_pjsua.call_hangup(call_id, 410, None, None)
		p_cont = 0

# Callback on incoming call transfer request
#		
def on_call_transfer_request(call_id, dst, code):
	write_log(3, "Call transfer request from " + `call_id` + " to " + dst + " with code " + `code`)

#
# Initialize pjsua.
#
def app_init():
	global g_acc_id, g_ua_cfg

	# Create pjsua before anything else
	status = py_pjsua.create()
	if status != 0:
		err_exit("pjsua create() error", status)

	# Create and initialize logging config
	log_cfg = py_pjsua.logging_config_default()
	log_cfg.level = C_LOG_LEVEL
	log_cfg.cb = log_cb

	# Create and initialize pjsua config
	# Note: for this Python module, thread_cnt must be 0 since Python
	#       doesn't like to be called from alien thread (pjsua's thread
	#       in this case)	    
	ua_cfg = py_pjsua.config_default()
	ua_cfg.thread_cnt = 0
	ua_cfg.user_agent = "PJSUA/Python 0.1"
	ua_cfg.cb.on_incoming_call = on_incoming_call
	ua_cfg.cb.on_call_media_state = on_call_media_state
	ua_cfg.cb.on_reg_state = on_reg_state
	ua_cfg.cb.on_call_state = on_call_state
	ua_cfg.cb.on_buddy_state = on_buddy_state
	ua_cfg.cb.on_pager = on_pager
	ua_cfg.cb.on_pager_status = on_pager_status
	ua_cfg.cb.on_typing = on_typing
	ua_cfg.cb.on_call_transfer_status = on_call_transfer_status
	ua_cfg.cb.on_call_transfer_request = on_call_transfer_request

	# Create and initialize media config
	med_cfg = py_pjsua.media_config_default()
	med_cfg.ec_tail_len = 0

	#
	# Initialize pjsua!!
	#
	status = py_pjsua.init(ua_cfg, log_cfg, med_cfg)
	if status != 0:
		err_exit("pjsua init() error", status)

	# Configure STUN config
	stun_cfg = py_pjsua.stun_config_default()
	stun_cfg.stun_srv1 = C_STUN_SRV
	stun_cfg.stun_srv2 = C_STUN_SRV
	stun_cfg.stun_port1 = C_STUN_PORT
	stun_cfg.stun_port2 = C_STUN_PORT

	# Configure UDP transport config
	transport_cfg = py_pjsua.transport_config_default()
	transport_cfg.port = C_SIP_PORT
	transport_cfg.stun_config = stun_cfg
	if C_STUN_SRV != "":
		transport_cfg.use_stun = 1

	# Create UDP transport
	status, transport_id = \
	    py_pjsua.transport_create(py_pjsua.PJSIP_TRANSPORT_UDP, transport_cfg)
	if status != 0:
		py_pjsua.destroy()
		err_exit("Error creating UDP transport", status)

	# Create initial default account
	status, acc_id = py_pjsua.acc_add_local(transport_id, 1)
	if status != 0:
		py_pjsua.destroy()
		err_exit("Error creating account", status)

	g_acc_id = acc_id
	g_ua_cfg = ua_cfg

# Add SIP account interractively
#
def add_account():
	global g_acc_id

	acc_domain = ""
	acc_username = ""
	acc_passwd =""
	confirm = ""
	
	# Input account configs
	print "Your SIP domain (e.g. myprovider.com): ",
	acc_domain = sys.stdin.readline()
	if acc_domain == "\n": 
		return
	acc_domain = acc_domain.replace("\n", "")

	print "Your username (e.g. alice): ",
	acc_username = sys.stdin.readline()
	if acc_username == "\n":
		return
	acc_username = acc_username.replace("\n", "")

	print "Your password (e.g. secret): ",
	acc_passwd = sys.stdin.readline()
	if acc_passwd == "\n":
		return
	acc_passwd = acc_passwd.replace("\n", "")

	# Configure account configuration
	acc_cfg = py_pjsua.acc_config_default()
	acc_cfg.id = "sip:" + acc_username + "@" + acc_domain
	acc_cfg.reg_uri = "sip:" + acc_domain
	acc_cfg.cred_count = 1
	acc_cfg.cred_info[0].realm = acc_domain
	acc_cfg.cred_info[0].scheme = "digest"
	acc_cfg.cred_info[0].username = acc_username
	acc_cfg.cred_info[0].data_type = 0
	acc_cfg.cred_info[0].data = acc_passwd

	# Add new SIP account
	status, acc_id = py_pjsua.acc_add(acc_cfg, 1)
	if status != 0:
		py_pjsua.perror(THIS_FILE, "Error adding SIP account", status)
	else:
		g_acc_id = acc_id
		write_log(3, "Account " + acc_cfg.id + " added")

def add_player():
	global g_wav_files
	global g_wav_id
	global g_wav_port
	
	file_name = ""
	status = -1
	wav_id = 0
	
	print "Enter the path of the file player(e.g. /tmp/audio.wav): ",
	file_name = sys.stdin.readline()
	if file_name == "\n": 
		return
	file_name = file_name.replace("\n", "")
	status, wav_id = py_pjsua.player_create(file_name, 0)
	if status != 0:
		py_pjsua.perror(THIS_FILE, "Error adding file player ", status)
	else:
		g_wav_files.append(file_name)
		if g_wav_id == 0:
			g_wav_id = wav_id
			g_wav_port = py_pjsua.player_get_conf_port(wav_id)
		write_log(3, "File player " + file_name + " added")
		
def add_recorder():
	global g_rec_file
	global g_rec_id
	global g_rec_port
	
	file_name = ""
	status = -1
	rec_id = 0
	
	print "Enter the path of the file recorder(e.g. /tmp/audio.wav): ",
	file_name = sys.stdin.readline()
	if file_name == "\n": 
		return
	file_name = file_name.replace("\n", "")
	status, rec_id = py_pjsua.recorder_create(file_name, 0, None, 0, 0)
	if status != 0:
		py_pjsua.perror(THIS_FILE, "Error adding file recorder ", status)
	else:
		g_rec_file = file_name
		g_rec_id = rec_id
		g_rec_port = py_pjsua.recorder_get_conf_port(rec_id)
		write_log(3, "File recorder " + file_name + " added")

def conf_list():
	ports = None
	print "Conference ports : "
	ports = py_pjsua.enum_conf_ports()

	for port in ports:
		info = None
		info = py_pjsua.conf_get_port_info(port)
		txlist = ""
		for i in range(info.listener_cnt):
			txlist = txlist + "#" + `info.listeners[i]` + " "
		
		print "Port #" + `info.slot_id` + "[" + `(info.clock_rate/1000)` + "KHz/" + `(info.samples_per_frame * 1000 / info.clock_rate)` + "ms] " + info.name + " transmitting to: " + txlist
		
def connect_port():
	src_port = 0
	dst_port = 0
	
	print "Connect src port # (empty to cancel): "
	src_port = sys.stdin.readline()
	if src_port == "\n": 
		return
	src_port = src_port.replace("\n", "")
	src_port = int(src_port)
	print "To dst port # (empty to cancel): "
	dst_port = sys.stdin.readline()
	if dst_port == "\n": 
		return
	dst_port = dst_port.replace("\n", "")
	dst_port = int(dst_port)
	status = py_pjsua.conf_connect(src_port, dst_port)
	if status != 0:
		py_pjsua.perror(THIS_FILE, "Error connecting port ", status)
	else:		
		write_log(3, "Port connected from " + `src_port` + " to " + `dst_port`)
		
def disconnect_port():
	src_port = 0
	dst_port = 0
	
	print "Disconnect src port # (empty to cancel): "
	src_port = sys.stdin.readline()
	if src_port == "\n": 
		return
	src_port = src_port.replace("\n", "")
	src_port = int(src_port)
	print "From dst port # (empty to cancel): "
	dst_port = sys.stdin.readline()
	if dst_port == "\n": 
		return
	dst_port = dst_port.replace("\n", "")
	dst_port = int(dst_port)
	status = py_pjsua.conf_disconnect(src_port, dst_port)
	if status != 0:
		py_pjsua.perror(THIS_FILE, "Error disconnecting port ", status)
	else:		
		write_log(3, "Port disconnected " + `src_port` + " from " + `dst_port`)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -