📄 grammarmanager.cpp
字号:
if (answer->results == NULL) { log.LogError(420, SimpleLogger::MESSAGE, L"function returned a null results vector"); return GrammarManager::InternalError; } unsigned int NUM_ANSWERS = VXIVectorLength(answer->results); if (NUM_ANSWERS == 0) { log.LogError(420, SimpleLogger::MESSAGE, L"function returned an empty results vector"); return GrammarManager::InternalError; } const VXIMap * bestAnswer = NULL; for (unsigned int i = 0; i < NUM_ANSWERS; ++i) { // (3.2) Find each element in the result vector. const VXIValue * temp = VXIVectorGetElement(answer->results, i); if (temp == NULL) { log.LogError(400, SimpleLogger::MESSAGE, L"VXIVectorGetElement failed to return answer."); return GrammarManager::InternalError; } if (VXIValueGetType(temp) != VALUE_MAP) { log.LogError(420, SimpleLogger::MESSAGE, L"function returned an invalid results vector"); return GrammarManager::InternalError; } const VXIMap * nthAnswer = reinterpret_cast<const VXIMap*>(temp); if (i == 0) bestAnswer = nthAnswer; // (3.3) Validate types of member keys. temp = VXIMapGetProperty(nthAnswer, REC_KEYS); if (temp == NULL || VXIValueGetType(temp) != VALUE_VECTOR) { log.LogError(420, SimpleLogger::MESSAGE, L"REC_KEYS must be defined with type vector"); return GrammarManager::InternalError; } const VXIVector * keys = reinterpret_cast<const VXIVector *>(temp); temp = VXIMapGetProperty(nthAnswer, REC_VALUES); if (temp == NULL || VXIValueGetType(temp) != VALUE_VECTOR) { log.LogError(420, SimpleLogger::MESSAGE, L"REC_VALUES must be defined with type vector"); return GrammarManager::InternalError; } const VXIVector * values = reinterpret_cast<const VXIVector *>(temp); temp = VXIMapGetProperty(nthAnswer, REC_CONF); if (temp == NULL || VXIValueGetType(temp) != VALUE_VECTOR) { log.LogError(420, SimpleLogger::MESSAGE, L"REC_CONF must be defined with type vector"); return GrammarManager::InternalError; } const VXIVector * scores = reinterpret_cast<const VXIVector *>(temp); temp = VXIMapGetProperty(nthAnswer, REC_RAW); if (temp == NULL || VXIValueGetType(temp) != VALUE_VECTOR) { log.LogError(420, SimpleLogger::MESSAGE, L"REC_RAW must be defined with type vector"); return GrammarManager::InternalError; } const VXIVector * utts = reinterpret_cast<const VXIVector *>(temp); // (3.4) Validate vector lengths. const VXIunsigned length = VXIVectorLength(keys); if (length < 1) { log.LogError(420, SimpleLogger::MESSAGE, L"result vector must have length of at least one"); throw VXIException::Fatal(); } if (length != VXIVectorLength(values) || length != VXIVectorLength(scores) || length != VXIVectorLength(utts)) { log.LogError(420, SimpleLogger::MESSAGE, L"result vector length must all match"); return GrammarManager::InternalError; } temp = VXIVectorGetElement(keys, 0); if (temp == NULL || VXIValueGetType(temp) != VALUE_STRING) { log.LogError(420, SimpleLogger::MESSAGE, L"first REC_KEYS must be defined with type string"); return GrammarManager::InternalError; } // (3.5) Copy into results class. recAnswer.keys.push_back(keys); recAnswer.values.push_back(values); recAnswer.scores.push_back(scores); recAnswer.utts.push_back(utts); } recAnswer.numAnswers = NUM_ANSWERS; // (4) Find the VXML element associated with the matched grammar. // (4.1) Find the grammar corresponding to the best answer. const VXIValue * temp = VXIMapGetProperty(bestAnswer, REC_GRAMMAR); if (temp == NULL || VXIValueGetType(temp) != VALUE_PTR) { log.LogError(420, SimpleLogger::MESSAGE, L"unable to obtain grammar key from 'results' #0"); return GrammarManager::InternalError; } const VXIPtr * tempptr = reinterpret_cast<const VXIPtr *>(temp); const VXIrecGrammar * bestGrammar = reinterpret_cast<const VXIrecGrammar*>(VXIPtrValue(tempptr)); // (4.2) Map the VXIrecGrammar pointer back to the source VXMLElement. for (GRAMMARS::iterator j = grammars.begin(); j != grammars.end(); ++j) { if ((*j)->GetRecGrammar() != bestGrammar) continue; if (!(*j)->IsEnabled()) { log.LogError(420, SimpleLogger::MESSAGE, L"function returned an inactive grammar"); return GrammarManager::InternalError; } (*j)->GetElement(recNode); if (answer->mode == REC_INPUT_MODE_DTMF) return GrammarManager::SuccessDTMF; return GrammarManager::Success; } log.LogError(420, SimpleLogger::MESSAGE, L"function returned a non-existent grammar"); return GrammarManager::InternalError;}int GrammarManager::Record(const VXIMapHolder & properties, VXIrecRecordResult * & resultStruct){ // (1) Do record. VXIrecResult err = vxirec->Record(vxirec, properties.GetValue(), &resultStruct); if (err == VXIrec_RESULT_OUT_OF_MEMORY) { log.LogDiagnostic(0, L"GrammarManager::Record - Out of memory."); return GrammarManager::OutOfMemory; } if (err == VXIrec_RESULT_BAD_MIME_TYPE) { log.LogDiagnostic(0, L"GrammarManager::Record - Unsupported mime type."); return GrammarManager::BadMimeType; } if (err != VXIrec_RESULT_SUCCESS) { log.StartDiagnostic(0) << L"GrammarManager::Record - " L"VXIrecInterface::Record returned " << int (err); log.EndDiagnostic(); log.LogError(421, SimpleLogger::MESSAGE, L"function did not return the expected VXIrecSUCCESS result"); return GrammarManager::InternalError; } if (resultStruct == NULL) { log.LogError(421, SimpleLogger::MESSAGE, L"function returned VXIrecSUCCESS but did not allocate " L"an answer structure"); return GrammarManager::InternalError; } // (2) Process all non-Successful results. switch (resultStruct->status) { case REC_STATUS_SUCCESS: // Record produced a recording break; case REC_STATUS_TIMEOUT: // No signal was detected return GrammarManager::Timeout; case REC_STATUS_ERROR: // An error aborted record return GrammarManager::Error; case REC_STATUS_DISCONNECT: // Caller has disconnected without a recording return GrammarManager::Disconnect; case REC_STATUS_FAILURE: // This should never happen return GrammarManager::InternalError; default: log.StartDiagnostic(0) << L"GrammarManager::InternalRecognize - " L"VXIrecInterface::Recognize returned status " << int (resultStruct->status); log.EndDiagnostic(); log.LogError(420, SimpleLogger::MESSAGE, L"function returned an invalid VXIrecStatus code"); return GrammarManager::InternalError; } // (3) Verify that in the success case, the information is valid. if (resultStruct->waveform == NULL) { log.LogError(421, SimpleLogger::MESSAGE, L"function did not produce a recording"); return GrammarManager::InternalError; } // Technically recordings could exceed an hour. These users may just // change the source. if (resultStruct->duration == 0 || resultStruct->duration > 3600000) { log.LogError(421, SimpleLogger::MESSAGE, L"function returned invalid recording duration"); return GrammarManager::InternalError; } return GrammarManager::Success;}VXIMap * GrammarManager::GetRecProperties(const PropertyList & props, int timeout) const{ VXIMapHolder m; if (m.GetValue() == NULL) throw VXIException::OutOfMemory(); // (1) Retrieve flattened property list. props.GetProperties(m); // (2) Convert & manipulate the properties. // TBD #pragma message ("GrammarManager::GetRecProperties - handle REC_RESULT_SAVE_WAVEFORM ???") // TBD #pragma message ("GrammarManager::GetRecProperties - handle REC_RESULT_NBEST_SIZE ???") const VXIchar * j; VXIint time; VXIflt32 fraction; // (2.1) Language j = props.GetProperty(PropertyList::Language); if (j != NULL) AddParamValue(m, REC_LANGUAGE, j); // (2.2) Completion timeout j = props.GetProperty(PROP_COMPLETETIME); if (j != NULL && props.ConvertTimeToMilliseconds(log, j, time)) AddParamValue(m, REC_TIMEOUT_COMPLETE, time); // (2.3) Incompletion timeout j = props.GetProperty(PROP_INCOMPLETETIME); if (j != NULL && props.ConvertTimeToMilliseconds(log, j, time)) AddParamValue(m, REC_TIMEOUT_INCOMPLETE, time); // (2.4) Inter-Digit timeout j = props.GetProperty(PROP_INTERDIGITTIME); if (j != NULL && props.ConvertTimeToMilliseconds(log, j, time)) AddParamValue(m, REC_DTMF_TIMEOUT_INTERDIGIT, time); // (2.5) Inter-Digit timeout j = props.GetProperty(PROP_TERMTIME); if (j != NULL && props.ConvertTimeToMilliseconds(log, j, time)) AddParamValue(m, REC_DTMF_TIMEOUT_TERMINATOR, time); // (2.6) Confidence level j = props.GetProperty(PROP_CONFIDENCE); if (j != NULL && props.ConvertValueToFraction(log, j, fraction)) AddParamValue(m, REC_CONFIDENCE_LEVEL, fraction); // (2.7) Barge-in sensitivity level j = props.GetProperty(PROP_SENSITIVITY); if (j != NULL && props.ConvertValueToFraction(log, j, fraction)) AddParamValue(m, REC_SENSITIVITY, fraction); // (2.8) Performance tradeoff - speed vs. accuracy j = props.GetProperty(PROP_SPEEDVSACC); if (j != NULL && props.ConvertValueToFraction(log, j, fraction)) AddParamValue(m, REC_SPEED_VS_ACCURACY, fraction); // (2.9) DTMF terminator character j = props.GetProperty(PROP_TERMCHAR); if ((j != NULL) && (j[0] != L'\0')) { if (wcslen(j) == 1) AddParamValue(m, REC_DTMF_TERMINATOR_CHAR, j); else { log.StartDiagnostic(0) << L"GrammarManager::GetRecProperties - " L"Unable to set " << REC_DTMF_TERMINATOR_CHAR << L" from value \"" << j << L"\". Defaulting to '#'."; log.EndDiagnostic(); // Should we use the default, or rather not set anything ? AddParamValue(m, REC_DTMF_TERMINATOR_CHAR, L"#"); } } // (2.10) Input modes int mode = REC_INPUT_MODE_DTMF_SPEECH; j = props.GetProperty(PROP_INPUTMODES); if (j != NULL) { vxistring value(j); if (value == L"voice dtmf" || value == L"dtmf voice") mode = REC_INPUT_MODE_DTMF_SPEECH; else if (value == L"voice") mode = REC_INPUT_MODE_SPEECH; else if (value == L"dtmf") mode = REC_INPUT_MODE_DTMF; else { log.StartDiagnostic(0) << L"GrammarManager::GetRecProperties - " L"Unable to set " << REC_INPUT_MODES << L" from value \"" << value << L"\"."; log.EndDiagnostic(); } } AddParamValue(m, REC_INPUT_MODES, mode); // (2.11) Timeout settings if (timeout == -1) { j = props.GetProperty(PROP_TIMEOUT); if (j != NULL) PropertyList::ConvertTimeToMilliseconds(log, j, timeout); } if (timeout != -1) { AddParamValue(m, REC_DTMF_TIMEOUT, timeout); AddParamValue(m, REC_TIMEOUT, timeout); } // (3) Done return m.Release();}VXIMap * GrammarManager::GetRecordProperties(const PropertyList & props, int timeout) const{ VXIMapHolder m; if (m.GetValue() == NULL) throw VXIException::OutOfMemory(); // (1) Retrieve flattened property list. props.GetProperties(m); // (2) Convert & manipulate the properties. const VXIchar * j; VXIint time; // (2.1) Completion timeout j = props.GetProperty(GrammarManager::MaxTime); if (j != NULL && props.ConvertTimeToMilliseconds(log, j, time)) AddParamValue(m, REC_MAX_RECORDING_TIME, time); // (2.2) Final silence j = props.GetProperty(GrammarManager::FinalSilence); if (j != NULL && props.ConvertTimeToMilliseconds(log, j, time)) AddParamValue(m, REC_TIMEOUT_COMPLETE, time); // (2.3) Type j = props.GetProperty(GrammarManager::RecordingType); if (j != NULL) AddParamValue(m, REC_RECORD_MIME_TYPE, j); // (2.4) DTMF terminates record? j = props.GetProperty(GrammarManager::DTMFTerm); if (j != NULL) { int dtmfterm; if (vxistring(j) == L"false") dtmfterm = 0; else dtmfterm = 1; AddParamValue(m, REC_TERMINATED_ON_DTMF, dtmfterm); } // (2.5) Timeout settings if (timeout == -1) { j = props.GetProperty(PROP_TIMEOUT); if (j != NULL) PropertyList::ConvertTimeToMilliseconds(log, j, timeout); } if (timeout != -1) { AddParamValue(m, REC_DTMF_TIMEOUT, timeout); AddParamValue(m, REC_TIMEOUT, timeout); } // (3) Done return m.Release();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -