Reputation: 319
I'm trying to do a conference call between 2 asterisk extension, managed by pjsip. I want to call 123 and 124, and make them to talk.
I've set up two different transports and two accounts, this is not mandatory but it's the way I'm trying. To use a single account for both calls would be good anyway.
Problem is that the following code:
import pjsua
import threading
from time import sleep
def log_cb(level, str, len):
print str,
class MyAccountCallback(pjsua.AccountCallback):
sem = None
def __init__(self, account=None):
pjsua.AccountCallback.__init__(self, account)
def wait(self):
self.sem = threading.Semaphore(0)
self.sem.acquire()
def on_reg_state(self):
if self.sem:
if self.account.info().reg_status >= 200:
self.sem.release()
def cb_func(pid) :
print '%s playback is done' % pid
current_call.hangup()
# Callback to receive events from Call
class MyCallCallback(pjsua.CallCallback):
def __init__(self, call=None, dostuff=True):
pjsua.CallCallback.__init__(self, call)
self.dostuff=dostuff
# Notification when call state has changed
def on_state(self):
if not self.dostuff:
return
global current_call
global in_call
print "Call with", self.call.info().remote_uri,
print "is", self.call.info().state_text,
print "last code =", self.call.info().last_code,
print "(" + self.call.info().last_reason + ")"
#if self.call.info().media_state == pjsua.MediaState.ACTIVE:
# # Connect the call to sound device
# call_slot = self.call.info().conf_slot
# lib.conf_connect(call_slot, 0)
# lib.conf_connect(0, call_slot)
# print "Hello world, I can talk!"
if self.call.info().state == pjsua.CallState.DISCONNECTED:
current_call = None
print 'Current call is', current_call
in_call = False
elif self.call.info().state == pjsua.CallState.CONFIRMED:
print "Call Answred"
another_call = make_call(acc2, dst_uri2, dostuff=False)
conf_slot = self.call.info().conf_slot
conf_slot_2 = another_call.info().conf_slot
i = 0
while i < 10:
print '#####################################'
print '#####################################'
print 'conf_slot ' + str(conf_slot)
print 'conf_slot_2 ' + str(conf_slot_2)
print '#####################################'
print '#####################################'
if another_call.info().state == pjsua.CallState.CONFIRMED:
i = pjsua.Lib.instance()
i.conf_connect(conf_slot, conf_slot_2)
i.conf_connect(conf_slot_2, conf_slot)
else:
print '#####################################'
print 'FIRST CALL STATE %s' % self.call.info().__dict__
print '\n\n'
print 'ANOTHER CALL STATE %s' % another_call.info().__dict__
print '#####################################'
sleep(2)
i += 2
sleep(25)
self.call.hangup()
another_call.hangup()
in_call = False
# Notification when call's media state has changed.
def on_media_state(self):
if self.call.info().media_state == pjsua.MediaState.ACTIVE:
print "Media is now active"
else:
print "Media is inactive"
# Function to make call
def make_call(ac, uri, dostuff=True):
try:
print "Making call to", uri
return ac.make_call(uri, cb=MyCallCallback(dostuff=dostuff))
except pjsua.Error, e:
print "Exception: " + str(e)
return None
lib = pjsua.Lib()
try:
cfg = pjsua.MediaConfig()
lib.init(log_cfg = pjsua.LogConfig(level=4, callback=log_cb), media_cfg=cfg)
t1 = lib.create_transport(pjsua.TransportType.UDP, pjsua.TransportConfig(5081))
t2 = lib.create_transport(pjsua.TransportType.UDP, pjsua.TransportConfig(5082))
lib.set_null_snd_dev()
lib.start()
lib.handle_events()
acc_cfg = pjsua.AccountConfig()
acc_cfg.id = "sip:11111"
acc_cfg.reg_uri = "sip:localhost"
#acc_cfg.proxy = [ "sip:PROXY.YOURSIPSERVER.COM;lr" ]
acc_cfg.auth_cred = [ pjsua.AuthCred("*", "11111", "secret")]
acc_cb = MyAccountCallback()
acc = lib.create_account(acc_cfg, cb=acc_cb)
acc.set_transport(pjsua.Transport(lib, 1))
acc_cb.wait()
print "\n"
print "Registration complete, status=", acc.info().reg_status, \
"(" + acc.info().reg_reason + ")"
##########
# ACCO 2
##########
acc2_cfg = pjsua.AccountConfig()
acc2_cfg.id = "sip:11112"
acc2_cfg.reg_uri = "sip:localhost"
acc2_cfg.transport_id = t2._id
# a2cc_cfg.proxy = [ "sip:PROXY.YOURSIPSERVER.COM;lr" ]
acc2_cfg.auth_cred = [pjsua.AuthCred("*", "11112", "secret")]
acc2_cb = MyAccountCallback()
acc2 = lib.create_account(acc2_cfg, cb=acc2_cb)
acc2.set_transport(t2)
acc2_cb.wait()
###########
#YOURDESTINATION is landline or mobile number you want to call
dst_uri = "sip:123@localhost"
dst_uri2 = "sip:124@localhost"
in_call = True
lck = lib.auto_lock()
current_call = make_call(acc, dst_uri)
print 'Current call is', current_call
del lck
#wait for the call to end before shuting down
while in_call:
print('In call')
sleep(3)
pass
#sys.stdin.readline()
lib.destroy()
lib = None
except pjsua.Error, e:
print "Exception: " + str(e)
lib.destroy()
Produce the following result:
#####################################
In call
#####################################
#####################################
conf_slot 1
conf_slot_2 -1
#####################################
#####################################
#####################################
FIRST CALL STATE {'total_time': 6, 'account': <pjsua.Account instance at 0x7f9482f90ea8>, 'conf_slot': 1, 'sip_call_id': 'de7fe2e7-21c5-4763-a02b-a7a08ab20d02', 'uri': 'sip:11111', 'media_state': 1, 'last_reason': 'OK', 'remote_contact': '<sip:[email protected]:5060>', 'state': 5, 'contact': '<sip:127.0.0.1:5081;ob>', 'role': 0, 'state_text': 'CONFIRMED', 'media_dir': 3, 'remote_uri': 'sip:123@localhost', 'call_time': 6, 'last_code': 200}
ANOTHER CALL STATE {'total_time': 6, 'account': <pjsua.Account instance at 0x7f9482fa0200>, 'conf_slot': -1, 'sip_call_id': '094b998a-2b0c-42eb-b5ac-0a44251a6566', 'uri': 'sip:11112', 'media_state': 0, 'last_reason': '', 'remote_contact': '', 'state': 1, 'contact': '<sip:127.0.0.1:5082;ob>', 'role': 0, 'state_text': 'CALLING', 'media_dir': 0, 'remote_uri': 'sip:124@localhost', 'call_time': 0, 'last_code': 0}
#####################################
And the second call doesn't start. As it doesn't, I think the conf_slot is still -1, and it's so impossible to do the bridge:
i.conf_connect(conf_slot, conf_slot_2)
i.conf_connect(conf_slot_2, conf_slot)
Any hint would be very appreciated.
Upvotes: 1
Views: 894
Reputation: 11930
It seems that your second call is not established. You have a lot of code mixed. I will recomend you to try to get a call first working, using an external SIP client (in example empathy (https://en.wikipedia.org/wiki/Empathy_(software) + SIP plugin)
When you make work to get an incoming call with the conference bridge, then try to use 2 threads to manage 2 different endpoints. If a pjsip callback is busy (you use it until a long task end) other callbacks won't trigger so it is impossible to make it work.
Try to isolate Call/Account code creating custom classes and call from different threads.
Upvotes: 1