Problem with opening/closing audio devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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()



[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux