📄 iaxwrapper.cpp
字号:
// monitor input and output signal levels (audio)
event_level(e.ev.levels.input, e.ev.levels.output);
break;
case IAXC_EVENT_REGISTRATION:
// monitor registration status
event_registration(e.ev.reg.id, e.ev.reg.reply, e.ev.reg.msgcount);
break;
case IAXC_EVENT_TEXT:
event_text(e.ev.text.type, e.ev.text.message);
break;
case IAXC_EVENT_STATE:
event_state(e.ev.call.callNo, e.ev.call.state, e.ev.call.remote,
e.ev.call.remote_name, e.ev.call.local,
e.ev.call.local_context, e.ev.reg.id);
break;
default:
event_unknown(e.type);
break;
}
}
void IaxWrapper::event_level(float in, float out)
{
emit signalLevels((int)-in, (int) -out, (int) 0);
}
void IaxWrapper::event_registration(int id, int reply, int msgcount)
{
//debug("Registration id = %d, reply = %d, msgcount = %d\n", id, reply, msgcount);
Account * account = getAccountByRegistrationId(id);
if (account!=NULL)
{
switch (reply)
{
case IAXC_REGISTRATION_REPLY_ACK :
{
//account->setRegistrationAccepted(true);
//emit signalRegistrationAccepted(account);
account->setState(ACCOUNT_ACCEPTED);
break;
}
case IAXC_REGISTRATION_REPLY_REJ :
{
//account->setRegistrationAccepted(false);
//emit signalRegistrationRejected(account);
account->setState(ACCOUNT_REJECTED);
break;
}
case IAXC_REGISTRATION_REPLY_TIMEOUT :
{
//emit signalRegistrationTimeout(account);
account->setState(ACCOUNT_TIMEOUT);
break;
}
}
}
}
void IaxWrapper::event_state(int callNo, int state, char *remote, char *remote_name,
char *local, char *local_context, int reg_id)
{
QString func = "IaxWrapper::event_state()";
//debug (func+" processing IAX event..\n");
/* Call state masks */
bool free = state & IAXC_CALL_STATE_FREE;
bool active = state & IAXC_CALL_STATE_ACTIVE;
bool outgoing = state & IAXC_CALL_STATE_OUTGOING;
bool ringing = state & IAXC_CALL_STATE_RINGING;
bool complete = state & IAXC_CALL_STATE_COMPLETE;
bool selected = state & IAXC_CALL_STATE_SELECTED;
bool busy = state & IAXC_CALL_STATE_BUSY;
bool transfer = state & IAXC_CALL_STATE_TRANSFER;
//debug (func+" call state %d : active=%d, outgoing=%d, ringing=%d, complete=%d, selected=%d registrationId=%d\n", callNo, active, outgoing, ringing, complete, selected, reg_id);
// remove the pass (when we are in outgoing call, it is visible)
QString remoteStr = QString(remote_name);
// store here remote_name with suppressed pass
QString modifiedStr = QString::fromUtf8("");
int passStart = remoteStr.indexOf(QString::fromUtf8(":"), 0, Qt::CaseInsensitive) + 1;
int passEnd = remoteStr.indexOf(QString::fromUtf8("@"), 0, Qt::CaseInsensitive);
int passLength = passEnd-passStart;
if (passStart>0)
{
modifiedStr = remoteStr.replace(passStart,passLength,QString::fromUtf8("xxx"));
}
//debug (func+" call info %d : remote=%s, remote_name=%s, local=%s, local_context=%s\n", callNo, remote, (const char*)modifiedStr, local, local_context);
QString remoteContext(remote);
QString localName(local);
QString localContext(local_context);
QString remoteName(remote_name);
QString remoteExten = remote;
if (active)
{ // there is a call progress
//ougoing calls
if ((outgoing) && ringing)
{
//debug(func+" ACTIVE_OUTGOING_RINGING %d : %s, reigstrationId = %d\n",callNo, (const char *) remoteExten, reg_id);
// we are making the call so we have already created a record
CallRecord& record = callSession[callNo];
record.setOutgoing(true);
record.setIncoming(false);
record.setActive(true);
emit signalOutgoingRinging(callNo);
}
// incoming calls
if ((!outgoing)&& ringing)
{
//debug(func+" ACTIVE_INCOMING_RINGING %d: %s, registrationId = %d\n",callNo, (const char *) remoteExten, reg_id);
CallRecord * record = createCallRecord(settings->getDefaultAccountId(), remoteName, remoteExten, false);
callSession[callNo] = *record;
int accountNumber = findAccountById(record->getAccountId());
configureCall(accountNumber);
record->setOutgoing(false);
record->setIncoming(true);
record->setActive(true);
emit signalIncomingRinging(callNo);
}
// incoming and outgoing, but active
if (complete && &selected)
{
//debug(func+" ACTIVE_CALL_ESTABLISHED %d: %s\n",callNo, (const char *) remoteExten);
// we have already answered the call so we have a created record
CallRecord& record = callSession[callNo];
if (!record.isAnswered())
{
record.setCallStartTime(QString::number(QDateTime::currentDateTime().toTime_t()));
}
if (!callDurationTimer->isActive())
{
callDurationTimer->start(1000); // notify every second
}
record.setAnswered(true);
record.setActive(true);
emit signalComplete(callNo);
}
}
else
{
// there is no call progress, hangup
//debug(func+" INACTIVE %d\n", callNo);
CallRecord& record = callSession[callNo];
if (callSession.count()==1) //stop the timer only if this is the only call
callDurationTimer->stop();
if (record.isAnswered()) record.setCallEndTime(QString::number(QDateTime::currentDateTime().toTime_t()));
record.save();
record.setActive(false);
emit signalInactive(callNo);
}
// Added by RND for extended states
if (free)
{
emit signalFree();
}
if (busy)
{
emit signalBusy(callNo);
}
if (transfer)
{
emit signalTransfer(callNo);
}
}
void IaxWrapper::event_text(int type, char *message)
{
if (message)
{
//debug( "IaxWrapper::event_text() Message: Type=%d Message=%s\n", type, message);
switch(type)
{
case IAXC_TEXT_TYPE_STATUS:
emit signalTextMessage(message);
break;
}
}
}
void IaxWrapper::event_unknown(int type)
{
//debug( "IaxWrapper::event_unknown() Uknown message: Type=%d\n", type);
}
void IaxWrapper::fatal_error(QString err)
{
emit fatalError(err);
}
/*
Implements a customEvent handler for posted messages
from iaxc_callback. This solves the problem of asynchronous
access to the GUI thread.
*/
void IaxWrapper::iaxWrapperEvent(IaxWrapperEvent * event)
{
handleIaxCEvent(event->iaxClientEvent);
}
CallRecord* IaxWrapper::createCallRecord(QString accountId, QString name, QString number, bool outgoing)
{
CallRecord * record = new CallRecord();
record->setAccountId(accountId);
record->setCallerIdName(name);
record->setCallerIdNumber(number);
record->setOutgoing(outgoing);
record->setAnswered(false);
return record;
}
/*
Private methods
*/
uint IaxWrapper::getCodecMaskFromName(QString codecName)
{
if (codecName == QString::fromUtf8("ilbc"))
return IAXC_FORMAT_ILBC;
if (codecName==QString::fromUtf8("gsm"))
return IAXC_FORMAT_GSM;
if (codecName==QString::fromUtf8("alaw"))
return IAXC_FORMAT_ALAW;
if (codecName==QString::fromUtf8("ulaw"))
return IAXC_FORMAT_ULAW;
if (codecName==QString::fromUtf8("speex"))
return IAXC_FORMAT_SPEEX;
// if none of them for some reason...
return IAXC_FORMAT_ULAW;
}
void IaxWrapper::configureCall(int accountNumber)
{
QString func = QString::fromUtf8("IaxWrapper::configureCall(acc number ") + QString::number(accountNumber) + QString::fromUtf8(")");
//debug( func+" configuring call..\n");
Account * account = settings->getAccount(accountNumber);
//debug( func+" account number=%d, account alias=%s\n",accountNumber,(const char*)account->accAlias);
// get Caller ID info
char* c_callerId = qstrdup( (account->callerId).toAscii() );
//debug( func+" callerId=%s\n",c_callerId);
char * c_callerIdNumber = qstrdup( (account->callerIdNumber).toAscii() );
//debug( func+" callerIdNumber=%s\n",c_callerIdNumber);
iaxc_set_callerid(c_callerId, c_callerIdNumber);
// get preferred codec - default ILBC
iaxc_set_formats( getCodecMaskFromName(account->codec), IAXC_FORMAT_GSM|IAXC_FORMAT_SPEEX|IAXC_FORMAT_ULAW|IAXC_FORMAT_ILBC);
//debug( func+" codec=%s\n",(const char*)account->codec);
// turn on filters
int flag = settings->getFilterFlag();
//debug( func+" filter flag=%d\n",flag);
iaxc_set_filters(flag);
// set silence threshold (1-auto, 0 - mute)
iaxc_set_silence_threshold(settings->getSilenceThreshold());
//debug( func+" silence threshold=%d\n",settings->getSilenceThreshold());
// set up audio devices
iaxc_audio_devices_set(settings->getInputDevice(),settings->getOutputDevice(), settings->getRingDevice());
//debug( func+" devices in=%d, out=%d, ring=%d\n",settings->getInputDevice(), settings->getOutputDevice(), settings->getRingDevice());
iaxc_set_audio_output(0); //umute output (if muted for some reason)
}
/*
Portions of tone generation code from iaxComm's Ringer Class
(c) Michael Van Donselaar
*/
iaxc_sound* IaxWrapper::initTone(int F1, int F2, int Dur, int Len, int Repeat)
{
iaxc_sound* tone;
tone = (iaxc_sound *)malloc(sizeof(iaxc_sound));
tone->channel = 1;
tone->len = Len;
tone->data = (short *)calloc(tone->len , sizeof(short));
for( int i=0;i < Dur; i++ )
{
tone->data[i] = (short)(0x7fff*0.4*sin((double)i*F1*M_PI/8000))
+ (short)(0x7fff*0.4*sin((double)i*F2*M_PI/8000));
}
tone->repeat = Repeat;
return tone;
}
void IaxWrapper::ring()
{
ringInTone = initTone(1900, 2400, 400,500,20);
iaxc_play_sound(ringInTone, 1);
}
void IaxWrapper::startRing()
{
ring(); // start ringing, the timer will wait and then ring again
ringTimer->start();
}
void IaxWrapper::stopRing()
{
/* In case there was no ring signal.. we have to check*/
if (ringInTone!= NULL) {
iaxc_stop_sound(ringInTone->id);
delete ringInTone;
}
ringTimer->stop();
ringInTone=NULL;
}
void IaxWrapper::callDuration()
{
QMutexLocker locker(&callSessionMutex); /* to synchronize access to callSession */
int callsNumber = callSession.count();
for (int i=0;i<callsNumber;i++)
{
int hours = 0;
int minutes = 0;
int seconds = 0;
int callNumber = callSession.keys()[i];
int callStartTime=strtol( ( callSession[callNumber].getCallStartTime() ).toAscii(),0,10);
uint currentTime = QDateTime::currentDateTime().toTime_t();
uint interval = currentTime - callStartTime;
div_t hours_calc = div(interval, 3600);
hours = hours_calc.quot;
div_t minutes_calc = div(hours_calc.rem, 60);
minutes = minutes_calc.quot;
seconds = minutes_calc.rem;
//debugStatistics(callNumber, interval);
if (callSession[callNumber].isAnswered()) /* display time only if the call was answered */
emit callTime(callNumber, hours, minutes, seconds);
}
}
bool IaxWrapper::getShowStats()
{
return showStats;
}
void IaxWrapper::setShowStats(bool flag)
{
showStats = flag;
}
bool IaxWrapper::isCallActive()
{
if ( (this->callSession.count()>0) && ( this->callSession[this->getSelectedCall()].isActive()) )
{
return true;
}
else
{
return false;
}
}
QString IaxWrapper::getIaxClientVersion()
{
return QString(iaxc_ver);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -