Custom Action Example

There is often a need to look information up in a database. The following example will show how to set up a Custom Action dynamic link library. The call flow which the CA DLL will support is shown below.

This example will focus on the PinNumber Module support. The other modules and their CA functions may be mentioned, but will not be detailed here. The first issue will be our User Data. This will be defined in a header of the Custom Action DLL project.

C++ Code

  1. struct AccountInfo
  2. {
  3. LONG AccountNo;
  4. LONG PinNo;
  5. LONG StateCode;
  6. LONG CityCode;
  7. CHAR SocialSec[20];
  8. LONG Age;
  9. };

The LV_Call_Start function is a recommended function that will be called if found in the CA DLL. This function will receive notification that a call is starting. This is a very good place to create and store the User Data.

C++ Code

  1. __declspec(dllexport) BOOL WINAPI LV_Call_Start(LONG nMsg, HANDLE hCA)
  2. {
  3. AccountInfo* pAI = new AccountInfo;
  4. memset(pAI, 0, sizeof(AccountInfo));
  5. if(!LVCA_SetUserData(hCA, pAI))
  6. {
  7. /*
  8.         error An Error is anything within the system
  9.         itself that creates a glitch in the Speech
  10.         Driven Information System, such as a missing
  11.         Vox or a Goto that doesn't go anywhere.handing;
  12.         */
  13. }
  14.  
  15. return true;
  16. }

When the call ends the LV_Call_End function will be called. This is the logical place to clean up the user data.

C++ Code

  1. __declspec(dllexport) BOOL WINAPI LV_Call_End(LONG nMsg, HANDLE hCA)
  2. {
  3. AccountInfo* pAI;
  4. if(!LVCA_GetUserData(hCA, (LPVOID *) &pAI))
  5. {
  6. //error handling;
  7. }
  8. delete pAI;
  9. LVCA_SetUserData(hCA, NULL);
  10. return true;
  11. }

A definition file should be created for the project. This text file specifies the exported functions. Here is an example of what the .def file would look like:

LIBRARY "CA_Test"
EXPORTS
LV_Call_Start
LV_Call_End

Here is how the PinNumber module will look in the Designer.

Notice there is no audio and the grammar has no concepts in it. The Custom DLL property has a Custom Action DLL filename. The function that the module is going to look for is PinModule. This function will need to be defined in the CA DLL.

C++ Code

  1. __declspec(dllexport) BOOL WINAPI PinModule(LONG nEvent, HANDLE hCA)
  2. {
  3. switch(nEvent)
  4. {
  5. case CAMSG_POLL:
  6. return TRUE;
  7. case CAMSG_ENTERMODULE:
  8. LVCA_AddMainLibraryAudio(hCA, "EnterPin");
  9. LVCA_AddStandardGrammar(hCA, CA_GRAMMAR_DIGITS);
  10. break;
  11. case CAMSG_REC_BEFORE_CONFIRM:
  12. CheckPin(hCA);
  13. break;
  14. }
  15. return TRUE;
  16. }

In the above example, notice that the CAMSG_ENTERMODULE has two functions being called. The LVCA_AddMainLibraryAudio function is adding audio, defined in the Designer's Audio Manager. LVCA_AddStandardGrammar is adding the built-in digits grammar. The event CAMSG_REC_BEFORE_CONFIRM is calling CheckPin. The function needs to extract the raw concept and save it as a pin number in the user data. Since it is possible for the concept to be a Designer defined grammar, the LVCA_IsCustom function checks the response.

C++ Code

  1. VOID CheckPin(HANDLE hCA)
  2. {
  3. LONG nCount;
  4. LONG nSize = 1024;
  5. LONG nConf = 0;
  6. if (!LVCA_GetRawConceptCount(hCA, &nCount))
  7. {
  8. INT nErr = LVCA_GetLastCallError(hCA, m_szErrStr, &nSize);
  9. if(!nErr)
  10. nErr = LVCA_GetLastSystemError(m_szErrStr, &nSize);
  11. ReportError(nErr);
  12. return;
  13. }
  14. BOOL bIsCustom;
  15. TCHAR szConcept[1024];
  16.  
  17. //for brevity just getting the first concept;
  18.  
  19. if(!LVCA_GetRawConcept(hCA, 0, szConcept, &nSize, &nConf))
  20. {
  21. //error handling
  22. }
  23. if(!LVCA_IsCustomConcept(hCA, &bIsCustom, szConcept))
  24. {
  25. //error handling
  26. }
  27. if(!bIsCustom) //this protects a global concept from being intercepted
  28.  
  29. return;
  30. AccountInfo* pAI;
  31. if(!LVCA_GetUserInfo(hCA, (LPVOID *) &pAI)
  32. {
  33. //error handling
  34. }
  35. pAI->PinNo = atol(szConcept);
  36. //this function would perform a database lookup on the account and pin.
  37. if(!Login(pAI))
  38. {
  39. LVCA_AddOneTimeLibraryAudio(hCA, "Bad Pin Number or Account");
  40. LVCA_SetGoto(hCA, "AccountNo");
  41. }
  42. else
  43. {
  44. LVCA_SetGoto(hCA, "User Settings Needed");
  45. }
  46. }

Finally, the PinModule function needs to be added to the .def file.

LIBRARY "CA_Test"
EXPORTS
LV_Call_Start
LV_Call_End
PinModule

© 2012 LumenVox LLC. All rights reserved.