📄 iaxwrapper.cpp
字号:
#include "iaxwrapper.h"
#include <QMessageBox>
IaxWrapper* callbackCaller;
/*
Global method used as callback function in libiaxclient
Forwards incoming events to void IaxWrapper::handleIaxCEvent(void* callbackCaller, iaxc_event e) via customEvent(QCustomEvent)
*/
int iaxc_callback(iaxc_event e)
{
// wrap iaxc_event into a QEvent
IaxWrapperEvent * wrapperEvent = new IaxWrapperEvent(e);
QApplication::postEvent(callbackCaller, wrapperEvent);
return 1;
}
/*
Initialization and destruction of the wrapper
*/
IaxWrapper::IaxWrapper(QObject *parent, const char *name)
: QObject(parent)
{
this->setObjectName(name);
this->showStats = false;
this->registered=false; // we are not ready to call
callbackCaller = this; // to use it in the class callback function
//load the settings prior to do anything else
this->settings = new Prefs(this,0);
this->settings->loadSettings();
/* allocate memory for the statistics vars*/
this->rtt = (int*) malloc(sizeof(int));
this->localNetstat = (struct iaxc_netstat*) malloc(sizeof(struct iaxc_netstat));
this->remoteNetstat = (struct iaxc_netstat*) malloc(sizeof(struct iaxc_netstat));
this->ringInTone = NULL;
this->ringTimer = new QTimer(); // repeats ringing every 4 seconds
this->callDurationTimer = new QTimer(); // shows duration of the time every second
connect(ringTimer, SIGNAL(timeout()), this, SLOT(ring()));
connect(callDurationTimer, SIGNAL(timeout()), this, SLOT(callDuration()));
char* version = (char*)malloc(256);
this->iaxc_ver = iaxc_version(version);
//debug("Using IAXClient ver. %s\n", iaxc_ver);
}
IaxWrapper::~IaxWrapper()
{
this->shutdown_iax_client();
}
Prefs* IaxWrapper::getSettings()
{
return this->settings;
}
/*
High-level Methods interfacing the wrapped libiaxclient functions
*/
void IaxWrapper::registerWithServer()
{
// start the action
this->start_iax_client();
this->registerMultipleAccounts();
/*
Initially the idea was to enable controls for dialing only if we have Reigstration
Accepted, but letting the people use the controls even if not registered is OK as we may
have such servers that don't allow/require/need registration but allow calling.
*/
this->registered = true;
// and tell the GUI to enable "unregister" button or other
//emit signalRegistered();
}
int IaxWrapper::registerAccount(Account* account) {
//const char* func = "IaxWrapper::registerMultipleAccounts()";
// ("%s registering accounts..\n", func);
//const char* accName = (account->accAlias).toAscii();
char* uname = qstrdup( (account->username).toAscii() );
char* passwd = qstrdup( (account->password).toAscii() );
char* hst = qstrdup( (account->iaxServer).toAscii() );
if ( (account->registerAccount) && (account->iaxServer != ""))
{
// tell to an Asterisk server where we are
account->iaxRegistrationId = iaxc_register(uname, passwd, hst);
// ("%s register %s [%s:xxx@%s], given ID = %d\n", func, accName, uname, hst, account->iaxRegistrationId);
emit signalRegistrationRequested(account);
}
else
{
// ("%s skipped registration %s [%s:xxx@%s]\n", func, accName,uname, hst);
account->iaxRegistrationId = -1; //skipped
}
return account->iaxRegistrationId;
}
int IaxWrapper::unregisterAccount(Account* account) {
int result = -1;
if (account->iaxRegistrationId != -1)
{
result = iaxc_unregister(account->iaxRegistrationId);
//emit signalUnregistrationRequested(account);
account->setState(ACCOUNT_INACTIVE);
}
return result;
}
void IaxWrapper::registerMultipleAccounts()
{
// loop through all accounts and call register
for (int i=0; i<settings->getAccounts().count(); i++)
{
Account * account = settings->getAccount(i);
this->registerAccount(account);
}
}
void IaxWrapper::unregisterFromServer()
{
for (int i=0; i<settings->getAccounts().count(); i++) {
Account* account = settings->getAccount(i);
if ((account->registerAccount) &&(account->state != ACCOUNT_INACTIVE))
{
unregisterAccount(account);
account->disconnect(SIGNAL(signalRegistrationAccepted(Account*)));
account->disconnect(SIGNAL(signalRegistrationConnecting(Account*)));
account->disconnect(SIGNAL(signalRegistrationInactive(Account*)));
account->disconnect(SIGNAL(signalRegistrationRejected(Account*)));
account->disconnect(SIGNAL(signalRegistrationTimeout(Account*)));
}
}
this->stop_iax_client();
this->registered=false;
emit signalUnregistered();
}
int IaxWrapper::findAccountById(QString accountId)
{
int accNumber =0;
// locate the number of the account
for (int i=0; i<settings->getAccounts().count(); i++)
if (accountId==settings->getAccount(i)->accId)
{
accNumber=i;
break;
}
return accNumber;
}
void IaxWrapper::dial(QString accountId, QString contactName, QString contactNumber)
{
CallRecord * callRecord = createCallRecord(accountId, contactName, contactNumber, true);
int accountNumber = findAccountById(callRecord->getAccountId());
Account* account = settings->getAccount(accountNumber);
QString uname = account->username;
QString passwd = account->password;
QString hst = account->iaxServer;
if (this->registered) // if user is allowed to dial
{
QString full_url = uname+QString::fromUtf8(":")+passwd+QString::fromUtf8("@")+hst+QString::fromUtf8("/")+callRecord->getCallerIdNumber();
const char *dest = "";
configureCall(accountNumber);
if (hst!=QString::fromUtf8(""))
{
dest = full_url.toAscii();
}
else
{
dest = (callRecord->getCallerIdNumber()).toAscii();
}
// first, emit signal to notify the GUI //
// then call our friend
//debug( "IaxWrapper::dial(int, QString) dialing %s:%s@%s/%s ..\n", (const char*)uname, "xxx", (const char*) hst, (const char*)callRecord->getCallerIdNumber());
iaxc_call(qstrdup(dest));
callSession[getSelectedCall()] = *callRecord;
emit signalCalling(getSelectedCall(), QString::fromUtf8("Calling..."));
}
}
/*
Methods interfacing directly with libiaxclient
*/
bool IaxWrapper::init_iax_client()
{
int result = iaxc_initialize(AUDIO_INTERNAL,getSettings()->getMaxCalls());
//debug( "IaxWrapper::iaxc_initialize() result = %d\n", result);
if (result == -1)
{
// hopefully not many people will have to read this..
this->fatal_error(QString::fromUtf8("cannot initialize iaxclient!\n"));
return false;
}
iaxc_set_formats(IAXC_FORMAT_GSM,IAXC_FORMAT_GSM|IAXC_FORMAT_SPEEX|IAXC_FORMAT_ALAW|IAXC_FORMAT_ULAW|IAXC_FORMAT_ILBC);
return true;
}
void IaxWrapper::shutdown_iax_client()
{
// shutdown
//debug( "IaxWrapper::shutdown_iax_client() shutting down..\n");
iaxc_shutdown();
//debug( "IaxWrapper::shutdown_iax_client() done.\n");
}
void IaxWrapper::start_iax_client()
{
// we want iaxevents to be passed to iaxc_callback
iaxc_set_event_callback(iaxc_callback);
// fire
//debug( "IaxWrapper::start_iax_client() starting processing thread..\n");
int result = iaxc_start_processing_thread();
//debug( "IaxWrapper::iaxc_start_processing_thread() result = %d\n", result);
if (result == -1)
this->fatal_error(QString::fromUtf8("cannot start processing thread!\n"));
}
void IaxWrapper::stop_iax_client()
{
// close any active calls
iaxc_dump_all_calls();
// wait a bit
iaxc_millisleep(1000);
// stop the thread
iaxc_stop_processing_thread();
// reset type of call
}
void IaxWrapper::send_dtmf(char digit)
{
// allow sending dtmf only if we are in a state of a call (ACTIVE)
// TODO: this is a cheap version - has to be changed
if (this->registered)
{
//printf ("IaxWrapper::send_dtmf(char digit) sending DTMF%c\n", digit);
// I like playing with these voice menus
iaxc_send_dtmf(digit);
}
}
void IaxWrapper::answer_call(int callNumber)
{
QString func = QString::fromUtf8("IaxWrapper::answer_call()");
// answer the call
iaxc_answer_call(callNumber);
// (func+" answered call %d\n", getSelectedCall());
// notify GUI
emit signalAnsweredCall(callNumber);
}
void IaxWrapper::transfer_call(int callNo, QString number)
{
QString func = QString::fromUtf8("IaxWrapper::transfer_call(")+number+QString::fromUtf8(")");
// answer the call
const char* exten = number.toAscii();
iaxc_blind_transfer_call(callNo, qstrdup(exten) );
// (func+" transferred call %d\n", callNo);
}
void IaxWrapper::select_call(int callNumber)
{
QString func = QString::fromUtf8("IaxWrapper::select_call(")+QString::number(callNumber)+QString::fromUtf8(")");
//debug(func,"\n");
iaxc_select_call(callNumber);
// (func+" selected call %d\n", getSelectedCall());
}
void IaxWrapper::hold_call(int callNumber)
{
QString func = QString::fromUtf8("IaxWrapper::hold_call()");
// answer the call
iaxc_quelch(callNumber, 0);
// (func+" hold call %d\n", callNumber);
// notify GUI
CallRecord& record = callSession[callNumber];
record.setCustomProperty(QString::fromUtf8("isHold"),QString::fromUtf8("true"));
emit signalHoldCall(callNumber);
}
void IaxWrapper::resume_call(int callNumber)
{
QString func = QString::fromUtf8("IaxWrapper::resume_call()");
// answer the call
iaxc_unquelch(callNumber);
//KiaxCallRecord * record = callSession.at(getSelectedCall());
CallRecord& record = callSession[callNumber];
record.setCustomProperty(QString::fromUtf8("isHold"), QString::fromUtf8("false"));
//debug (func+" resume call %d\n", callNumber);
// notify GUI
emit signalResumedCall(callNumber);
}
void IaxWrapper::reject_call(int callNo)
{
QString func = QString::fromUtf8("IaxWrapper::reject_call()");
//debug(func+" rejecting call %d..\n", callNo);
iaxc_reject_call_number(callNo);
//debug(func+" rejected call %d\n", callNo);
}
void IaxWrapper::interrupt_call()
{
//printf("IaxWrapper::interrupt_call() hanging up and exiting..\n");
// hang up the call
iaxc_dump_call();
// wait a bit
iaxc_millisleep(1000);
}
int IaxWrapper::getSelectedCall()
{
return iaxc_selected_call();
}
Account* IaxWrapper::getAccountByRegistrationId(int regId) {
int number = settings->getAccounts().count();
for (int i=0;i<number;i++)
{
Account* account = settings->getAccount(i);
if (account->iaxRegistrationId==regId)
return account;
}
return NULL;
}
// Overwridden function to capture user( IAX ) events
bool IaxWrapper::event(QEvent * e)
{
if (e->type() == QEvent::User)
{
IaxWrapperEvent *wrapperEvent = static_cast<IaxWrapperEvent*>(e);
this->handleIaxCEvent(wrapperEvent->iaxClientEvent);
return true;
}
else
{
return false;
}
}
/*
Procedures handling iaxclient events (forwarded from iaxc_callback(iaxc_event e)
*/
void IaxWrapper::handleIaxCEvent(iaxc_event e)
{
switch(e.type)
{
case IAXC_EVENT_LEVELS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -