⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iaxwrapper.cpp

📁 YakaPhone, 著名的VOIP客户端, 需要使用iax库和QT库.界面很漂亮
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#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 + -