Hello,
I am trying to develop a pjsip app which will manage more usb sound devices
concurrently.
I am using PJSIP 2.8 .
I am trying to manage the case in which a device is disconnected by fault
at runtime and reconnected again without restarting the application.
What I do today is at the startup I start a timer and at each timeout I
call :
AudDevManager& mgr = Endpoint::instance().audDevManager();
mgr.refreshDevs();
I iterate over the available devices and if I didn't create them
before I create them in this way:
bool VCSSoundDevMgr::createAudioDevice(int deviceID, AudioDevInfo info)
{
try
{
pj_status_t status;
pjsua_ext_snd_dev * snd_dev;
/* Generate sound device port param */
pjmedia_snd_port_param param;
pjmedia_snd_port_param_default(¶m);
status = pjmedia_aud_dev_default_param(deviceID, ¶m.base);
if(status!= PJ_SUCCESS)
{
qDebug()<<"VCSSoundDevMgr::createAudioDevice -
pjmedia_aud_dev_default_param error";
}
param.base.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
param.base.play_id = deviceID;
param.base.rec_id = deviceID;
param.base.clock_rate = master_info.clock_rate;
param.base.channel_count = master_info.channel_count;
param.base.samples_per_frame = master_info.samples_per_frame;
param.base.bits_per_sample = master_info.bits_per_sample;
status = pjsua_ext_snd_dev_create(¶m, &snd_dev);
if(status!= PJ_SUCCESS)
{
qDebug()<<"VCSSoundDevMgr::createAudioDevice - cannot
create device:"<<deviceID;
}
else
{
int slotID = pjsua_ext_snd_dev_get_conf_port(snd_dev);
AudioDeviceInfo *s = new AudioDeviceInfo();
QString devName = QString::fromStdString(info.name);
s->device = snd_dev;
s->info = info;
s->slot = slotID;
s->friendly_name = mDeviceNames.value(devName,devName);
mAudioDevices.insert(devName, s);
qDebug()<<"VCSSoundDevMgr::createAudioDevice - created
Sound Dev:"<<devName<<" ID:"<<deviceID<<" slot:"<<slotID;
}
}
catch(Error &err)
{
qDebug()<<"VCSSoundDevMgr::createSoundDeviceSlot() - error:"
<< err.info().c_str();
return false;
}
return true;
}
At each timeout i also iterate over the devices already created to
check if they are still connected simply by calling :
bool VCSSoundDevMgr::isDeviceConnected(QString name)
{
AudDevManager& mgr = Endpoint::instance().audDevManager();
try
{
mgr.lookupDev("ALSA", name.toStdString());
return true;
}
catch (Error& e)
{
return false;
}
}
In case it is disconnected, I create a thread to destroy the sound
device in this way:
void VCSSoundDevMgr::destroyAudioDevice(AudioDeviceInfo *info)
{
qDebug()<<"Destroying device..";
pj_status_t status;
try
{
AudioMediaVector vector = Endpoint::instance().mediaEnumPorts();
foreach(AudioMedia * media, vector)
{
if(media->getType() == PJMEDIA_TYPE_AUDIO)
{
pjsua_conf_disconnect(media->getPortId(), info->slot);
pjsua_conf_disconnect(info->slot, media->getPortId());
}
}
qDebug()<<"Disconnected calls..";
pj_pool_t *pool = pjsua_pool_create("pool",4000,4000);
pj_thread_t *pjThread;
//CREATE THREAD
status = pj_thread_create (pool,
"soundevmgr_destroy",
threadDestroy,
info->device,
0, //ZERO,
0,
&pjThread);
if (status != PJ_SUCCESS)
{
qDebug() << "VCSSoundDevMgr::destroySoundDevices() -
WARNING: pj_thread_create is not created.";
pj_thread_join(pjThread);
pj_thread_destroy(pjThread);
}
mAudioDevices.remove(QString::fromStdString(info->info.name));
delete info;
info = NULL;
qDebug()<<"DEVICE DELETED";
}catch(Error &err)
{
qDebug() << "VCSSoundDevMgr::destroyAudioDevice() - ERROR: "
<< err.info().c_str();
}
}
static int threadDestroy (void *arg)
{
/* Check if we have sound stream device. */
pj_status_t status;
//REGISTERING THREAD
pj_thread_desc aPJThreadDesc;
pj_thread_t *pjThread;
if (!pj_thread_is_registered()) {
status = pj_thread_register("soundevmgr_destroy",
aPJThreadDesc, &pjThread);
qDebug()<<"VCSSoundDevMgr::destroySoundDevices() - registered thread";
if (status != PJ_SUCCESS) {
qDebug() << "VCSSoundDevMgr::destroySoundDevices() -
WARNING: pjthread is not registered.";
}
}
pjsua_ext_snd_dev * dev = (pjsua_ext_snd_dev *)arg;
status = pjsua_ext_snd_dev_destroy(dev);
if(status != PJ_SUCCESS)
{
qDebug() << "VCSSoundDevMgr::destroyAudioDevice - "
<< "pjsua_ext_snd_dev_destroy error";
}
qDebug()<<"THREAD TERMINATED..";
return PJ_SUCCESS;
}
Until here, everything works great!
I turn on the application, the devices are created, I disconnect a device
from the USB, the application destroy the sound device.
MY PROBLEM COMES NOW:
When I plug-in the device that I previously disconnected the
AudioDeviceManager sees the device, try to create it but this step in the
creation returns an error:
status = pjmedia_aud_dev_default_param(deviceID, ¶m.base);
And the device cannot be created because it results it has zero output
and zero input count.
Basically after some investigation I think that alsa_dev.c is setting
those counts to zero because
it fails to do snd_pcm_open on this device. But how come at the
beginning it was possible to open it and when I plug it in again not?
Is there any one that can help me understand why this happens?
Thanks in advance.
Shani