//In vxml.h //----------- //Prototype event_set MenuAlgorithm( rtp_info_t* rtp, DOM_Node firstMenuNode); //In vxml.cpp //------------- else if( childNode.getNodeName().equals( "form" ) || childNode.getNodeName().equals( "menu" ) ) { /** * A
or tag is found */ //... rest of the code } //In vxml.cpp //------------- event_set event; if( first_found ) { if( firstFormNode.getNodeName().equals( "menu" ) ) { TRACE("Found a menu tag"); DOM_Node firstMenuNode = firstFormNode; event = MenuAlgorithm( &rtp, firstMenuNode); TRACE("MenuAlgorithm complete now in main"); } //... rest of the code } /** /* Interpretation Model of a menu * A menu behaves like a form with a single field that does all the work. * The menu prompts become field prompts. The menu event handlers become * the field event handlers. The menu grammars become form grammars. * Upon entry, the menu's grammars are built and enabled, and the prompt * is played. When the user input matches a choice, control transitions * according to the value of the next attribute of the , only one * of which may be specified. * * @param rtp is the associated context. * * @param firstMenuNode is the the menu node * * @param doc is the document node * * @return the event set indicating where to go next * */ event_set MenuAlgorithm( rtp_info_t* rtp, DOM_Node firstMenuNode) { bool dtmfAttribute = false; DOM_Node menuItem = firstMenuNode; vector choice; std::string choiceContent; //if dtmf attribute of the menu tag is true the choices' dtmf grammars //are implicit if( menuItem.getAttributes() != NULL ) { DOM_Node dtmf; if( ( dtmf = menuItem.getAttributes().getNamedItem( "dtmf" ) ) != NULL ) { TRACE("menu has dtmf attribute"); char* p= dtmf.getNodeValue().transcode(); if( !strcmp(p,"true") ) dtmfAttribute = true; delete[] p; }//if dtmf }//if menuItem event_set event; FIA_ResetEvent(event); int implicitDtmf = 0; //build the grammar and the transition destination FOREACH( child, menuItem.getChildNodes(),{ DOMString name = child.getNodeName(); if( name.equals( "choice" ) ){ if( child.getAttributes() != NULL ){ //We only support the next attribute for this element DOM_Node next = child.getAttributes().getNamedItem( "next" ); if( !dtmfAttribute ){ DOM_Node dtmf = child.getAttributes().getNamedItem( "dtmf" ); } DOM_Node text = child.getAttributes().getNamedItem( "#text" ); if( text != NULL ){ choiceContent += FIA_GetTextPart( text ); } if( next != NULL ){ char* pNext = next.getNodeValue().transcode(); if( pNext != NULL ){ if( !dtmfAttribute && dtmf != NULL ){ char* pDtmf = dtmf.getNodeValue().transcode(); if( pDtmf != NULL && pNext != NULL ){ int choiceNumber = atoi( pDtmf ); choice[ choiceNumber ] = pDtmf; } delete[] pDtmf; }//if dtmfattribute else{ choice[ implicitDtmf++ ] = pNext; } }//if pNext delete[] pNext; }//if next else{ TRACE("We only support next attribute for choice"); } }//if choice's attributes }//if choice });//foreach std::string prompt=""; bool enumEmpty=false; FOREACH( child,menuItem.getChildNodes(),{ DOMString name = child.getNodeName(); if( name.equals( "prompt" ) ){ std::string v = FIA_GetPrompt( child, menuItem ); prompt += v; }//prompt else if( name.equals( "enumerate" ) ){ if( child.getChildNodes == NULL ) enumEmpty = true; }//enumerate });//FOREACH if( prompt != "" ){ if( enumEmpty ){ //Add choice contents to the prompt prompt += choiceContent; }//enumEmpty TTS_EnqueueText(rtp,prompt); } else{ TRACE("No prompt for this menu"); } //get user input and match them against active grammars for the menu //user_input_t user_input; if( rtp != NULL ){ //reset the current_input to ignore previously detected digits rtp->current_input = ""; double timeout=0; //in second struct timespec ts; while( true ){ int retcode=0; bool queue_empty = FIA_IsSendQueueEmpty(rtp); struct timeval now; gettimeofday( &now, NULL ); ts = timespec_delay( now, timeout ); retcode = pthread_cond_timedwait(&rtp->cond_vxml, &rtp->mutex_vxml, &ts); TRACE("MenuAlgorithm - getting user input"); if( rtp->oTerminateVxml ){ TRACE("MenuAlgorithm - oTerminate is true"); break; } TRACE("Calling IsSendQueueEmpty"); bool queue_empty_after = FIA_IsSendQueueEmpty(rtp); TRACE("Result is "<current_input != "" ){ std::string current_input = rtp->current_input; if( rtp->current_input[rtp->current_input.size() - 1] == '#'){ TRACE( "Input is # terminated" ); current_input.erase( current_input.size()-1, 1); }//# terminated if( current_input == "**" ){ TRACE( "Help Requested" ); event.event = "help"; return( event ); }//help else{ char* ptr = current_input.c_str(); int userChoice = atoi( ptr ); if( choice[ userChoice ] != NULL ){ TRACE( "Matched"); event.event = "matched"; event.goto_next = choice[ userChoice ]; return( event ); }//choice } else{ event.event = "nomatch"; return( event ); } }//current_input }//while }//if rtp not null return( event ); }//MenuAlgorithm