00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <bogotel/portability.h>
00011 #include <bogotel/TermParms.h>
00012 #include <bogotel/VoiceDev.h>
00013 #include <bogotel/Timer.h>
00014 #include <bogotel/IOOp.h>
00015 #include <bogotel/util.h>
00016
00017 #include <stdexcept>
00018
00019 #include <dxtables.h>
00020
00021 #include <deque>
00022
00023 namespace bogotel {
00024
00025 typedef std::deque<char> DEQUE_CHAR;
00026
00027 CTermParms::CTermParms(CVoiceDev* pVD, CIOOp* pIOOp, const DV_TPT* pTpt) throw (std::invalid_argument) :
00028 m_pVD(pVD),
00029 m_pIOOp(pIOOp),
00030 m_pTpt(NULL),
00031 m_currSpeakerState(CVoiceDev::speakerState::UNDEFINED),
00032 m_uiStartingSpeakerStateId(pVD->getStateId()),
00033 m_strDtmf(""),
00034 m_iNumDtmfsPressed(0)
00035 {
00036 char method[] = "CTermParms::CTermParms";
00037 log(9, "%s: Entered.", method);
00038
00039 copyTpt(pTpt);
00040
00041
00042 m_pVD->attach(this);
00043
00044 log(9, "%s: Completed.", method);
00045 }
00046
00047 CTermParms::~CTermParms()
00048 {
00049
00050 DV_TPT* pCurrTpt = m_pTpt;
00051 while (pCurrTpt) {
00052 DV_TPT* pNextTpt = pCurrTpt->tp_nextp;
00053 delete pCurrTpt;
00054 pCurrTpt = pNextTpt;
00055 }
00056
00057 m_pVD->detach(this);
00058 }
00059
00060
00061
00062
00063
00064 void CTermParms::start()
00065 {
00066 initialCheck();
00067 _update();
00068 }
00069
00070 void CTermParms::update(CSubject* theChangedSubject)
00071 {
00072 char method[] = "CTermParms::update";
00073 log(9, "%s: Entered. Parent IO Op: %s", method, m_pIOOp->toString().c_str());
00074
00075
00076
00077 if (m_uiStartingSpeakerStateId == m_pVD->getStateId()) {
00078 log(9, "%s: Completed. device SpeakerStateId same as at start", method);
00079 return;
00080 }
00081
00082 m_currSpeakerState = m_pVD->getState();
00083
00084 switch (m_currSpeakerState) {
00085 case CVoiceDev::speakerState::DTMF:
00086 m_iNumDtmfsPressed++;
00087 log(9, "%s: Increasing m_iNumDtmfsPressed to %d", method, m_iNumDtmfsPressed);
00088 break;
00089 case CVoiceDev::speakerState::SILENT:
00090 case CVoiceDev::speakerState::WAV:
00091 break;
00092 default:
00093 log(3, "%s: Unknown state. %d", method, m_currSpeakerState);
00094 break;
00095 }
00096
00097 m_pIOOp->incStateId();
00098
00099 _update();
00100
00101 log(9, "%s: Completed.", method);
00102 }
00103
00104 void CTermParms::timerExpired(int timerType, int stateId)
00105 {
00106 char method[] = "CTermParms::timerExpired";
00107 log(9, "%s: Entered.", method);
00108
00109
00110 int lTermMask;
00111 switch (timerType) {
00112 case timerType::IddTime:
00113 lTermMask = TM_IDDTIME;
00114 break;
00115 case timerType::MaxTime:
00116 lTermMask = TM_MAXTIME;
00117 break;
00118 case timerType::MaxSil:
00119 lTermMask = TM_MAXSIL;
00120 break;
00121 }
00122 m_pIOOp->terminate(lTermMask);
00123 log(9, "%s: Completed.", method);
00124 }
00125
00126 void CTermParms::initialCheck()
00127 {
00128 char method[] = "CTermParms::initialCheck";
00129 log(9, "%s: Entered.", method);
00130
00131 DV_TPT* pCurrTpt = const_cast<DV_TPT*>(m_pTpt);
00132
00133 long lTermMsk(0);
00134
00135 while(pCurrTpt && (lTermMsk == 0)) {
00136
00137 switch (pCurrTpt->tp_termno) {
00138 case DX_DIGMASK:
00139 if (pCurrTpt->tp_flags & TF_LEVEL) {
00140
00141
00142
00143 DEQUE_CHAR dequeDigitHistory = m_pVD->getDigitHistory();
00144 for (DEQUE_CHAR::iterator iterDigitHistory = dequeDigitHistory.begin();
00145 iterDigitHistory != dequeDigitHistory.end();
00146 iterDigitHistory++) {
00147 char chDigit = (*iterDigitHistory);
00148 if (inDigitMask(pCurrTpt->tp_length, chDigit)) {
00149 lTermMsk = TM_DIGIT;
00150
00151
00152 iterDigitHistory++;
00153 m_pVD->eraseFromDigitHistory(iterDigitHistory);
00154 break;
00155 }
00156 }
00157 } else {
00158
00159 m_pVD->eraseDigitHistory();
00160 }
00161 break;
00162 case DX_MAXDTMF:
00163 if (pCurrTpt->tp_flags & TF_LEVEL) {
00164
00165
00166 int iNumDtmfsPressedUntilNow(m_pVD->getDigitHistory().size());
00167 if (iNumDtmfsPressedUntilNow >= pCurrTpt->tp_length) {
00168 lTermMsk = TM_MAXDTMF;
00169
00170
00171 m_pVD->eraseFromDigitHistory(pCurrTpt->tp_length);
00172 } else {
00173 m_iNumDtmfsPressed = iNumDtmfsPressedUntilNow;
00174 }
00175 } else {
00176
00177 m_pVD->eraseDigitHistory();
00178 }
00179 break;
00180 default:
00181
00182 break;
00183 }
00184
00185 if (pCurrTpt->tp_type == IO_EOT) {
00186 pCurrTpt = NULL;
00187 } else {
00188 pCurrTpt = pCurrTpt->tp_nextp;
00189 }
00190 }
00191
00192 if (lTermMsk != 0) {
00193 log(7, "%s: calling terminate. termmsk %ld", method, lTermMsk);
00194 m_pIOOp->terminate(lTermMsk);
00195 }
00196
00197 log(9, "%s: Completed.", method);
00198 }
00199
00200 void CTermParms::_update()
00201 {
00202 char method[] = "CTermParms::_update";
00203 DV_TPT* pCurrTpt = const_cast<DV_TPT*>(m_pTpt);
00204 long lTermMsk(0);
00205 while(pCurrTpt) {
00206 switch (pCurrTpt->tp_termno) {
00207 case DX_MAXSIL:
00208 log(9, "%s: Processing DX_MAXSIL.", method);
00209 if (m_currSpeakerState == CVoiceDev::speakerState::SILENT) {
00210 long timerPeriod(pCurrTpt->tp_length);
00211 if (pCurrTpt->tp_flags & TF_10MS) {
00212 timerPeriod *= 10;
00213 } else {
00214 timerPeriod *= 100;
00215 }
00216 m_pIOOp->setTimer(timerPeriod, timerType::MaxSil);
00217 }
00218 break;
00219
00220 case DX_MAXTIME: {
00221 log(9, "%s: Processing DX_MAXTIME.", method);
00222 long timerPeriod(pCurrTpt->tp_length);
00223 if (pCurrTpt->tp_flags & TF_10MS) {
00224 timerPeriod *= 10;
00225 } else {
00226 timerPeriod *= 100;
00227 }
00228 m_pIOOp->setTimer(timerPeriod, timerType::MaxTime);
00229 break;
00230 }
00231
00232 case DX_IDDTIME:
00233 log(9, "%s: Processing DX_IDDTIME.", method);
00234 if (m_currSpeakerState == CVoiceDev::speakerState::SILENT) {
00235 long timerPeriod(pCurrTpt->tp_length);
00236 if (pCurrTpt->tp_flags & TF_10MS) {
00237 timerPeriod *= 10;
00238 } else {
00239 timerPeriod *= 100;
00240 }
00241 m_pIOOp->setTimer(timerPeriod, timerType::IddTime);
00242 }
00243 break;
00244
00245 case DX_DIGMASK:
00246 log(9, "%s: Processing DX_DIGMASK.", method);
00247 if (m_currSpeakerState == CVoiceDev::speakerState::DTMF) {
00248 if (inDigitMask(pCurrTpt->tp_length, m_pVD->getCurrentDtmf())) {
00249 lTermMsk |= TM_DIGIT;
00250
00251 m_pVD->eraseDigitHistory();
00252 }
00253 }
00254 break;
00255
00256 case DX_MAXDTMF:
00257 log(9, "%s: Processing DX_MAXDTMF.", method);
00258 if (m_currSpeakerState == CVoiceDev::speakerState::DTMF) {
00259 if (m_iNumDtmfsPressed == pCurrTpt->tp_length) {
00260 lTermMsk |= TM_MAXDTMF;
00261
00262 m_pVD->eraseDigitHistory();
00263 }
00264 }
00265 break;
00266
00267 default:
00268
00269
00270 break;
00271 }
00272
00273
00274 if (pCurrTpt->tp_type == IO_EOT) {
00275 pCurrTpt = NULL;
00276 } else {
00277 pCurrTpt = pCurrTpt->tp_nextp;
00278 }
00279 }
00280
00281 if (lTermMsk != 0) {
00282 log(7, "%s: calling terminate. termmsk %ld", method, lTermMsk);
00283 m_pIOOp->terminate(lTermMsk);
00284 } else {
00285 log(9, "%s: Completed.", method);
00286 }
00287 }
00288
00289 bool CTermParms::inDigitMask(unsigned short mask, char digit)
00290 {
00291 unsigned short maskInput(0);
00292 switch (digit) {
00293 case 'd': maskInput = DM_D; break;
00294 case '1': maskInput = DM_1; break;
00295 case '2': maskInput = DM_2; break;
00296 case '3': maskInput = DM_3; break;
00297 case '4': maskInput = DM_4; break;
00298 case '5': maskInput = DM_5; break;
00299 case '6': maskInput = DM_6; break;
00300 case '7': maskInput = DM_7; break;
00301 case '8': maskInput = DM_8; break;
00302 case '9': maskInput = DM_9; break;
00303 case '0': maskInput = DM_0; break;
00304 case '*': maskInput = DM_S; break;
00305 case '#': maskInput = DM_P; break;
00306 case 'a': maskInput = DM_A; break;
00307 case 'b': maskInput = DM_B; break;
00308 case 'c': maskInput = DM_C; break;
00309 default: break;
00310 }
00311 return (mask & maskInput) != 0;
00312 }
00313
00314 void CTermParms::log(int iLevel, char *szFmt, ...)
00315 {
00316 va_list vl;
00317 char szTemp[2000];
00318
00319 va_start(vl, szFmt);
00320 _vsnprintf(szTemp, sizeof(szTemp), szFmt, vl);
00321 va_end(vl);
00322
00323 g_util->log(iLevel, m_pVD->getSignalHandle(), szTemp);
00324 }
00325
00326
00327 void CTermParms::copyTpt(const DV_TPT* pTpt) throw (std::invalid_argument)
00328 {
00329 char method[] = "CTermParms::copyTpt";
00330 log(9, "%s: Entered.", method);
00331
00332 if (pTpt == NULL) {
00333 throw std::invalid_argument("TPT is null");
00334 }
00335
00336 int iNumEntries(0);
00337
00338 DV_TPT* pCurrTpt = const_cast<DV_TPT*>(pTpt);
00339 DV_TPT* pPreviousTpt = NULL;
00340 while(pCurrTpt) {
00341 iNumEntries++;
00342 DV_TPT* pNewTpt = new DV_TPT;
00343 pNewTpt->tp_termno = pCurrTpt->tp_termno;
00344 pNewTpt->tp_length = pCurrTpt->tp_length;
00345 pNewTpt->tp_flags = pCurrTpt->tp_flags;
00346 pNewTpt->tp_data = pCurrTpt->tp_data;
00347 pNewTpt->rfu = pCurrTpt->rfu;
00348 pNewTpt->tp_nextp = NULL;
00349
00350 if (m_pTpt == NULL) {
00351 m_pTpt = pNewTpt;
00352 } else {
00353 pPreviousTpt->tp_nextp = pNewTpt;
00354 }
00355
00356 switch (pCurrTpt->tp_type) {
00357 case IO_CONT:
00358 pCurrTpt++;
00359 pNewTpt->tp_type = IO_LINK;
00360 break;
00361 case IO_LINK:
00362 pCurrTpt = pCurrTpt->tp_nextp;
00363 pNewTpt->tp_type = IO_LINK;
00364 break;
00365 case IO_EOT:
00366 pCurrTpt = NULL;
00367 pNewTpt->tp_type = IO_EOT;
00368 break;
00369 }
00370 pPreviousTpt = pNewTpt;
00371 }
00372 log(9, "%s: Completed. Number of entries: %d", method, iNumEntries);
00373 }
00374
00375 }