2013-07-31 9 views
3

그래서 MSAPI 5.4 TTS with event example을 시도했습니다. 이제 SetNotifyCallbackFunction을 사용하는 cmd 프롬프트 응용 프로그램을 만들었지 만 전달한 함수가 호출되지 않습니다. 저는 C++ 전문가가 아니므로이 문제를 해결하는 데 어려움을 겪고 있습니다. 누군가 올바른 방향으로 나를 가리키거나 적어도 SetNotifyCallbackFunction의 좋은 예를 들어 주시겠습니까?C++ MSAPI 5 : SetNotifyCallbackFunction이 작동하지 않습니다.

여기 내 코드의 단순화 된 버전입니다 :

typedef void __stdcall SPNOTIFYCALLBACK(WPARAM wParam, LPARAM lParam); 

void __stdcall outsideeventFunction(WPARAM, LPARAM); 

void __stdcall outsideeventFunction(WPARAM wParam, LPARAM lParam){ 
    std::cout << "Event called::wParam: " << wParam << " lParam: " << lParam << std::endl; 
    SPEVENT eventItem; 
    memset(&eventItem, 0, sizeof(SPEVENT)); 
    while (SUCCEEDED(pV->GetEvents(1, &eventItem, NULL))) 
    { 
     bool exitNa = false; 
     switch (eventItem.eEventId) 
     { 
     case SPEI_WORD_BOUNDARY: 
      SPVOICESTATUS eventStatus; 
      pV->GetStatus(&eventStatus, NULL); 
      ULONG start, end; 
      start = eventStatus.ulInputWordPos; 
      end = eventStatus.ulInputWordLen; 
      std::cout << "From event Test: " << start << ", " << end << std::endl; 
      std::cout << "From event Length: " << theString.length() - 1 << ", " << start + end << std::endl; 
      if (theString.length() - 1 <= start + end){ 
       std::cout << "From event Exit!" << std::endl; 
       exitNa = true; 
      } 
      break; 
     } 

     SpClearEvent(&eventItem); 
     if (exitNa){ 
      break; 
     } 
    } 
    return; 
} 

int _tmain(int argc, TCHAR* argv [], TCHAR* envp []) 
{ 
    pV = NULL; 
    std::string nativeString("Hello world, this is a test! For the purpose of a longer message, I'll add another sentence. And here comes the new sentence."); 
    SPNOTIFYCALLBACK *cb = &outsideeventFunction; 
    if (FAILED(::CoInitialize(NULL))) 
     return FALSE; 

    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **) &pV); 
    if (SUCCEEDED(hr)) 
    { 
     if (SUCCEEDED(pV->SetNotifyCallbackFunction(cb, 0, 0))){ 
      std::cout << "Success adding callback" << std::endl; 
     } 

     ULONGLONG ullMyEvents = SPFEI(SPEI_WORD_BOUNDARY); 
     pV->SetInterest(ullMyEvents, ullMyEvents); 
    } 

    theString = std::wstring(nativeString.begin(), nativeString.end()); 

    printf("Speak: %s\n", nativeString.c_str()); 
    hr = pV->Speak(theString.c_str(), SPF_ASYNC, NULL); 
    pV->WaitUntilDone(INFINITE); 

    std::system("pause"); 
    pV->Release(); 
    pV = NULL; 
    ::CoUninitialize(); 
    return TRUE; 
} 

이 응용 프로그램의 결과는 단어의 합성이 원활하게 수행되지만, outsideeventFunction가 호출되지 않습니다이다. 보시다시피 SetInterest가 올바르게 설정되었습니다. 어떻게 해결할 수 있을까요?

1) SAPI는 이벤트 목표를 할당하지 않기 때문에

pV->SetNotifyWin32Event(); 

항상 실패 라인 :

+0

사용중인 음성 : 그래서 대신 이벤트가 설정 될 때까지 핸들 및 펌프 메시지를받을 필요가

pV->WaitUntilDone(INFINITE); 

를 호출? 일부 (Microsoft 이외의) 목소리는 이벤트에 문제가 있습니다 .... –

답변

3

두 문제.

2) 이벤트 전달을 위해 메시지를 보내야합니다.

HANDLE hWait = pV->SpeakCompleteEvent(); 
WaitAndPumpMessagesWithTimeout(hWait, INFINITE); 

HRESULT WaitAndPumpMessagesWithTimeout(HANDLE hWaitHandle, DWORD dwMilliseconds) 
{ 
    HRESULT hr = S_OK; 
    BOOL fContinue = TRUE; 

    while (fContinue) 
    { 
     DWORD dwWaitId = ::MsgWaitForMultipleObjectsEx(1, &hWaitHandle, dwMilliseconds, QS_ALLINPUT, MWMO_INPUTAVAILABLE); 
     switch (dwWaitId) 
     { 
     case WAIT_OBJECT_0: 
      { 
       fContinue = FALSE; 
      } 
      break; 

     case WAIT_OBJECT_0 + 1: 
      { 
       MSG Msg; 
       while (::PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) 
       { 
        ::TranslateMessage(&Msg); 
        ::DispatchMessage(&Msg); 
       } 
      } 
      break; 

     case WAIT_TIMEOUT: 
      { 
       hr = S_FALSE; 
       fContinue = FALSE; 
      } 
      break; 

     default:// Unexpected error 
      { 
       fContinue = FALSE; 
       hr = E_FAIL; 
      } 
      break; 
     } 
    } 
    return hr; 
} 
+0

아,이 사례에 대한 실험을 위해 그 줄을 넣었습니다. 그것 없이도 이벤트는 여전히 작동하지 않습니다. 더 이상의 제안? – Marl

+1

검토 기회를 얻고 실제 수정 사항을 추가했습니다 (이벤트를 전달하기 위해 메시지를 보내야 함). –