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

📄 iaxwrapper.cpp

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