Main Page   Namespace List   Class Hierarchy   Data Structures   File List   Namespace Members   Data Fields   Globals   Related Pages  

TermParms.cpp

Go to the documentation of this file.
00001 /*
00002  * TermParms.cpp
00003  *
00004  * Copyright 2003, MobileSpear Inc. (www.mobilespear.com). All rights reserved.
00005  * Copyright 2003, David Resnick. All rights reserved.
00006  *
00007  * See the file doc\license.txt for the terms of usage and distribution.
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         // attach to subject so that we will get updates on state changes
00042         m_pVD->attach(this);
00043 
00044         log(9, "%s: Completed.", method);
00045     }
00046 
00047     CTermParms::~CTermParms()
00048     {
00049         // delete local TPT
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     // do the first check for any termination conditions.
00061     // This was removed from the constructor because of the possibility
00062     // of there being an immediate terminate condition, calls CIoOp->terminate
00063     // before the constructor has finished.
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         // check if this "update" is relevent-- make sure that
00076         // the speaker state has changed since we were created
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         // inform IO operation of the termination condition
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             // check if we should terminate as a result of historical actions
00137             switch (pCurrTpt->tp_termno) {
00138             case DX_DIGMASK:
00139                 if (pCurrTpt->tp_flags & TF_LEVEL) {
00140                     // check historical digits for termination condition
00141 
00142                     // get copy of digit history
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                             // request removal of digits from beginning of history until
00151                             // (and including) the digit that met the terminating condition
00152                             iterDigitHistory++;
00153                             m_pVD->eraseFromDigitHistory(iterDigitHistory);
00154                             break;
00155                         }
00156                     }
00157                 } else {
00158                     // TPT level type is edge - erase digit history
00159                     m_pVD->eraseDigitHistory();
00160                 }
00161                 break;
00162             case DX_MAXDTMF:
00163                 if (pCurrTpt->tp_flags & TF_LEVEL) {
00164                     // check historical digits for termination condition
00165 
00166                     int iNumDtmfsPressedUntilNow(m_pVD->getDigitHistory().size());
00167                     if (iNumDtmfsPressedUntilNow >= pCurrTpt->tp_length) {
00168                         lTermMsk = TM_MAXDTMF;
00169                         // request removal of the number of digits in condition from 
00170                         // beginning of history
00171                         m_pVD->eraseFromDigitHistory(pCurrTpt->tp_length);
00172                     } else {
00173                         m_iNumDtmfsPressed = iNumDtmfsPressedUntilNow;
00174                     }
00175                 } else {
00176                     // TPT level type is edge - erase digit history
00177                     m_pVD->eraseDigitHistory();
00178                 }
00179                 break;
00180             default:
00181                 // in the meantime, we will not check for the LEVEL flag in other TPT entries
00182                 break;
00183             }
00184             // get next TPT entry to analyze
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                         // erase complete digit history
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                         // erase complete digit history
00262                         m_pVD->eraseDigitHistory();
00263                     }
00264                 }
00265                 break;
00266 
00267             default:
00268                 // ignore all other termination conditions;
00269                 // they are either not supported or irrelevant to a state change
00270                 break;
00271             }
00272 
00273             // get next TPT entry to analyze
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     // make a local copy of the TPT list
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             // get next TPT entry
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 }

Generated on Tue Aug 12 12:41:30 2003 for bogotel by doxygen 1.3. Hosted by SourceForge.net Logo