Beispiel #1
0
static void ShowPropertyValues(const VXIchar *key,
           const VXIValue *value, VXIunsigned PROP_TAG,
           VXIlogInterface *log)
{
  VXIchar subtag[512] = L"Property";
  if( value == 0 ) return;
  VXIvalueType type = VXIValueGetType(value);
  {
    switch( type )
    {
      case VALUE_INTEGER:
        wcscpy(subtag, L"Property:INT");
        Diag(log, PROP_TAG, subtag, 
             L"%s=%d", key, VXIIntegerValue((const VXIInteger*)value));
        break;
      case VALUE_FLOAT:
        wcscpy(subtag, L"Property:FLT");
        Diag(log, PROP_TAG, subtag, 
             L"%s=%f", key, VXIFloatValue((const VXIFloat*)value));
        break;
      case VALUE_BOOLEAN:     
        wcscpy(subtag, L"Property:BOOL");
        Diag(log, PROP_TAG, subtag, 
             L"%s=%d", key, VXIBooleanValue((const VXIBoolean*)value));
        break;
      case VALUE_STRING:
        wcscpy(subtag, L"Property:STR");
        Diag(log, PROP_TAG, subtag, 
             L"%s=%s", key, VXIStringCStr((const VXIString*)value));
        break;
      case VALUE_PTR:
        wcscpy(subtag, L"Property:PTR");
        Diag(log, PROP_TAG, subtag, 
             L"%s(ptr)=0x%p", key, VXIPtrValue((const VXIPtr*)value));
        break;
      case VALUE_CONTENT:
        wcscpy(subtag, L"Property:CNT");
        Diag(log, PROP_TAG, subtag, 
             L"%s(content)=0x%p", key, value);
        break;
      case VALUE_MAP:
        {
          VXIchar endtag[512];
          const VXIchar *mykey = key ? key : L"NULL";
          wcscpy(subtag, L"Property:MAP:BEG");
          wcscpy(endtag, L"Property:MAP:END");
          Diag(log, PROP_TAG, subtag, L"%s", mykey);
          const VXIchar *key = NULL;
          const VXIValue *gvalue = NULL;

          VXIMapIterator *it = VXIMapGetFirstProperty((const VXIMap*)value, &key, &gvalue);
          int ret = 0;
          while( ret == 0 && key && gvalue )
          {
            ShowPropertyValues(key, gvalue, PROP_TAG, log);
            ret = VXIMapGetNextProperty(it, &key, &gvalue);
          }
          VXIMapIteratorDestroy(&it);         
          Diag(log, PROP_TAG, endtag, L"%s", mykey);
        }   
        break;
      case VALUE_VECTOR:
        {
          VXIunsigned vlen = VXIVectorLength((const VXIVector*)value);
          for(VXIunsigned i = 0; i < vlen; ++i)
          {
            const VXIValue *gvalue = VXIVectorGetElement((const VXIVector*)value, i);
            ShowPropertyValues(L"Vector", gvalue, PROP_TAG, log);
          }
        }
        break;
      default:
        Diag(log, PROP_TAG, subtag, L"%s=%s", key, L"UNKOWN");
    }          
  }
  return;
}
Beispiel #2
0
// This function is responsible for calling the VXIrec level Recognize function
// and then mapping the grammar back to the corresponding VXML node.
//
int GrammarManager::Recognize(const VXIMapHolder & properties,
                              RecognitionAnswer & recAnswer,
                              VXMLElement & recNode)
{
  recNode = VXMLElement();
  VXIrecRecognitionResult * answer = NULL;

  // (1) Do VXIrec level Recognitize and process return value.

  // (1.1) Recognize.
  VXIrecResult err = vxirec->Recognize(vxirec, properties.GetValue(),
                                       &answer);
  if (err == VXIrec_RESULT_OUT_OF_MEMORY) {
    log.LogDiagnostic(0,L"GrammarManager::InternalRecognize - Out of memory.");
    return GrammarManager::OutOfMemory;
  }

  if (err == VXIrec_RESULT_DISCONNECT) {
    // Here is the case that the call is being disconnected before the 
    // recognition even starts
    return GrammarManager::Disconnect;
  }

  // (1.2) Anything other than success indicates that recognition failed
  // (badly).  The normal error conditions are returned through the recogntion
  // result structure.
  if (err != VXIrec_RESULT_SUCCESS) {
    log.StartDiagnostic(0) << L"GrammarManager::InternalRecognize - "
      L"VXIrecInterface::Recognize returned " << int (err);
    log.EndDiagnostic();
    log.LogError(420, SimpleLogger::MESSAGE,
                 L"function did not return the expected VXIrecSUCCESS result");
    return GrammarManager::InternalError;
  }

  // (1.3) The answer structure must be defined.
  if (answer == NULL) {
    // Here is the case that the call is being disconnected before the recording even starts
    return GrammarManager::Disconnect;
  }

  // (1.4) Attach the answer structure returned by VXIrec and the waveform to
  // the recAnswer class.
  recAnswer.Bind(answer);
  recAnswer.waveform = answer->waveform;

  // (2) Process all non-Successful results.

  // (2.1) First the status code.

  switch (answer->status) {
  case REC_STATUS_SUCCESS:    // Recognition returned a hypothesis
  case REC_STATUS_DTMFSUCCESS:    // Recognition returned a hypothesis
    break;
  case REC_STATUS_FAILURE:    // Speech detected, no likely hypothesis
    return GrammarManager::Failure;
  case REC_STATUS_TIMEOUT:    // No speech was detected
    return GrammarManager::Timeout;
  case REC_STATUS_DISCONNECT: // Caller has disconnected; no hypothesis
    return GrammarManager::Disconnect;
  case REC_STATUS_ERROR:      // An error aborted recognition
    return GrammarManager::Error;
  default:
    log.StartDiagnostic(0) << L"GrammarManager::InternalRecognize - "
      L"VXIrecInterface::Recognize returned status " << int(answer->status);
    log.EndDiagnostic();
    log.LogError(420, SimpleLogger::MESSAGE,
                 L"function returned an invalid VXIrecStatus code");
    return GrammarManager::InternalError;
  }

  // (2.2) Recognition success. Verify that the input mode was set correctly.

  switch (answer->mode) {
  case REC_INPUT_MODE_DTMF:
  case REC_INPUT_MODE_SPEECH:
    break;
  default:
    log.StartDiagnostic(0) << L"GrammarManager::InternalRecognize - "
      L"VXIrecInterface::Recognize returned mode " << int(answer->mode);
    log.EndDiagnostic();
    log.LogError(420, SimpleLogger::MESSAGE,
                 L"function returned an invalid VXIrecInputMode value");
    return GrammarManager::InternalError;
  }

  // (3) Walk through results array and sanity check the results.

  // (3.1) How many answers are there?

  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 ((answer->mode == REC_INPUT_MODE_DTMF && REC_STATUS_DTMFSUCCESS != answer->status) 
      && (*j)->GetRecGrammar() != bestGrammar) continue;

    if (!(*j)->IsEnabled()) 
    {
      if (j == grammars.end()) {
        log.LogError(420, SimpleLogger::MESSAGE,
                     L"function returned an inactive grammar");
        return GrammarManager::InternalError;
      }
      continue;
    }

    (*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;
}