Detecting Sleep Mode in SAPI

If you’ve done any development with the shared recognizer, you’ve probably had problems determining when the shared recognizer is in sleep mode.

Determining when the shared recognizer is OFF is easy enough; ISpRecognizer::GetRecoState will return SPRST_INACTIVE.

But figuring out the sleep state is much harder.  That’s because the shared recognizer is active (SPRST_ACTIVE_ALWAYS), but it’s not listening for all commands.

In Windows 7, there is a new interface that expose ‘categories’ (ISpRecognizer3). 

When WSR is sleeping, ISpRecognizer3::GetActiveCategory will return a non-null ISpRecoCategory of type SPCT_SLEEP

When WSR is listening, ISpRecognizer3::GetActiveCategory will return a null ISpRecoCategory

NOTE WELL:  This is only guaranteed to work on Windows 7.  It is not guaranteed to work on future versions of Windows.

Some sample code to get an ISpRecognizer3 interface from a shared recognizer stored in m_cpReco:

ISpRecognizer3 snippet

  1. CComPtr<ISpRecognizer3> cpReco3;
  2. hr = m_cpReco.QueryInterface<ISpRecognizer3>(&cpReco3);
  3. if (SUCCEEDED(hr))
  4. {
  5.     CComPtr<ISpRecoCategory> cpCategory;
  6.     hr = cpReco3->GetActiveCategory(&cpCategory);
  7.     if (SUCCEEDED(hr) && cpCategory != NULL)
  8.     {
  9.         SPCATEGORYTYPE spct;
  10.         hr = cpCategory->GetType(&spct);
  11.         if (SUCCEEDED(hr)
  12.         {
  13.             fIsSleeping = spct = SPCT_SLEEP;
  14.         }
  15.     }
  16. }

In order to make this work, you’ll need to have the Windows 7 SDK installed and set as default in Visual Studio.

Also, you’ll need to make sure that you have the following version numbers defined (typically in targetver.h):

#define WINVER 0x0601

#define _WIN32_WINNT 0x0601

This will enable the Windows-7 only interfaces like ISpRecognizer3.