Hi, I still have problems with a PJSUA application that I am writing. In this application, I can open the audio device for a voice connection only after the call has been established, and I need to close it exactly once at the end of the call. The issues that I have is that audio is not reliably working. Most of the time, no audio is sent or received, sometimes the audio starts but stops after 10-30 seconds. At connection end, I frequently see the application hang - GDB tells me that some thread is waiting for a lock. I feared that the problem was with my application, so I tried with a slightly hacked version of the Python API example to see whether that'd work better. It does not, though, and the problems are exactly the same as with my own software. Thus, I think the issue must be within PJSIP or PJSUA, but I don't know how to nail it down. The Python test program is below, maybe someone with more PJSUA/PJSIP experience can see what I'm doing wrong? I suspect that the issue is with the dynamic assignment of the audio device, but that is certainly just guesswork. Thanks, Hans import sys import pjsua as pj import threading current_call = None def log_cb(level, str, len): print str, class MyAccountCallback(pj.AccountCallback): register_sem = None def __init__(self, account): pj.AccountCallback.__init__(self, account) def wait(self): self.register_sem = threading.Semaphore(0) self.register_sem.acquire() def on_reg_state(self): if self.register_sem: if self.account.info().reg_status >= 200: self.register_sem.release() # Notification on incoming call def on_incoming_call(self, call): global current_call if current_call: call.answer(486, "Busy") return print "INCOMING", call.info().remote_uri current_call = call call_cb = MyCallCallback(current_call) current_call.set_callback(call_cb) current_call.answer(180) # Callback to receive events from Call class MyCallCallback(pj.CallCallback): def __init__(self, call=None): pj.CallCallback.__init__(self, call) self.media_active = False # Notification when call state has changed def on_state(self): global current_call print "STATE", self.call.info().state_text, print "CODE", self.call.info().last_code, print self.call.info().last_reason if self.call.info().state == pj.CallState.DISCONNECTED: current_call = None # Notification when call's media state has changed. def on_media_state(self): if self.call.info().media_state == pj.MediaState.ACTIVE: # Connect the call to sound device call_slot = self.call.info().conf_slot lib = pj.Lib.instance() lib.conf_connect(call_slot, 0) lib.conf_connect(0, call_slot) if self.call.info().state != pj.CallState.CONFIRMED: print "MEDIA active, but not confirmed" elif not self.media_active: lib.set_snd_dev(0, 0) print "MEDIA active" self.media_active = True else: print "MEDIA already active" else: self.media_active = False print "MEDIA inactive" # Function to make call def make_call(uri): try: print "CALLING", uri return acc.make_call(uri, cb=MyCallCallback()) except pj.Error, e: print "Exception: " + str(e) return None lib = pj.Lib() try: lib.init(log_cfg = pj.LogConfig(level=3, callback=log_cb)) transport = lib.create_transport(pj.TransportType.UDP, pj.TransportConfig(5080)) lib.start() for index, sound_device_info in enumerate(lib.enum_snd_dev()): direction = "" if sound_device_info.input_channels: direction = direction + "IN" if sound_device_info.output_channels: direction = direction + "OUT" print "SOUND_DEVICE", index, direction, sound_device_info.name # fixme - make asynchronous? acc = lib.create_account(pj.AccountConfig("prospan.huebner.org", "2000", "***")) lib.set_null_snd_dev() acc_cb = MyAccountCallback(acc) acc.set_callback(acc_cb) acc_cb.wait() print "REGISTRATION_COMPLETE", acc.info().reg_status, acc.info().reg_reason my_sip_uri = "sip:" + transport.info().host + ":" + str(transport.info().port) # Menu loop while True: print "SIP_URI", my_sip_uri input = sys.stdin.readline().rstrip("\r\n").split(); if input == []: continue command = input[0].upper(); if command == "CALL": if current_call: print "ERROR Already have another call" continue lck = lib.auto_lock() current_call = make_call(input[1]) del lck elif command == "HANGUP": if not current_call: print "ERROR There is no call" continue current_call.hangup() elif command == "ANSWER": if not current_call: print "ERROR There is no call" continue current_call.answer(200) elif command == "QUIT": break # Shutdown the library transport = None acc.delete() acc = None lib.destroy() lib = None except pj.Error, e: print "Exception: " + str(e) lib.destroy()