mirror of
https://github.com/ValveSoftware/source-sdk-2013.git
synced 2025-01-16 16:58:03 +03:00
Fixing Microsoft speech SDK based on the official Valve tutorial
This commit is contained in:
parent
0d8dceea43
commit
9beee1df69
BIN
mp/src/utils/sapi51/Bin/SAPI51ListBox.ocx
Normal file
BIN
mp/src/utils/sapi51/Bin/SAPI51ListBox.ocx
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Docs/Help/sapi.chm
Normal file
BIN
mp/src/utils/sapi51/Docs/Help/sapi.chm
Normal file
Binary file not shown.
2197
mp/src/utils/sapi51/IDL/sapi.idl
Normal file
2197
mp/src/utils/sapi51/IDL/sapi.idl
Normal file
File diff suppressed because it is too large
Load Diff
4847
mp/src/utils/sapi51/IDL/sapiaut.idl
Normal file
4847
mp/src/utils/sapi51/IDL/sapiaut.idl
Normal file
File diff suppressed because it is too large
Load Diff
818
mp/src/utils/sapi51/IDL/sapiddk.idl
Normal file
818
mp/src/utils/sapi51/IDL/sapiddk.idl
Normal file
@ -0,0 +1,818 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* sapiddk.idl
|
||||||
|
*
|
||||||
|
* This is the interface definition file for the Microsoft Speech API DLL's
|
||||||
|
* Version 5.0.
|
||||||
|
*
|
||||||
|
* It contains definitions for the DDI layer between SAPI.DLL and both
|
||||||
|
* TTS and SR engines.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
//--- Includes --------------------------------------------------------------
|
||||||
|
import "oaidl.idl";
|
||||||
|
import "ocidl.idl";
|
||||||
|
import "sapi.idl";
|
||||||
|
|
||||||
|
//--- Locally scoped define for LANGID
|
||||||
|
#ifndef LANGID
|
||||||
|
#define LANGID WORD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//--- ITN Processor
|
||||||
|
interface ISpITNProcessor;
|
||||||
|
|
||||||
|
//--- Grammar compiler and dynamic manipulation
|
||||||
|
interface ISpErrorLog;
|
||||||
|
interface ISpGrammarCompiler;
|
||||||
|
interface ISpGramCompBackend;
|
||||||
|
|
||||||
|
//--- Phrase builder
|
||||||
|
interface ISpPhraseBuilder;
|
||||||
|
|
||||||
|
//--- Token String Key Names
|
||||||
|
cpp_quote("#define SPRECOEXTENSION L\"RecoExtension\"")
|
||||||
|
cpp_quote("#define SPALTERNATESCLSID L\"AlternatesCLSID\"")
|
||||||
|
|
||||||
|
//--- ISpTokenUI -----------------------------------------------------------
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(F8E690F0-39CB-4843-B8D7-C84696E1119D),
|
||||||
|
helpstring("ISpTokenUI Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpTokenUI : IUnknown
|
||||||
|
{
|
||||||
|
[local] HRESULT IsUISupported(
|
||||||
|
[in] const WCHAR * pszTypeOfUI,
|
||||||
|
[in] void * pvExtraData,
|
||||||
|
[in] ULONG cbExtraData,
|
||||||
|
[in] IUnknown * punkObject,
|
||||||
|
[out] BOOL *pfSupported);
|
||||||
|
[local] HRESULT DisplayUI(
|
||||||
|
[in] HWND hwndParent,
|
||||||
|
[in] const WCHAR * pszTitle,
|
||||||
|
[in] const WCHAR * pszTypeOfUI,
|
||||||
|
[in] void * pvExtraData,
|
||||||
|
[in] ULONG cbExtraData,
|
||||||
|
[in] ISpObjectToken * pToken,
|
||||||
|
[in] IUnknown * punkObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
//--- ISpObjectTokenEnumBuilder ---------------------------------------------
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(06B64F9F-7FDA-11d2-B4F2-00C04F797396),
|
||||||
|
helpstring("ISpObjectTokensEnumBuilder Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpObjectTokenEnumBuilder : IEnumSpObjectTokens
|
||||||
|
{
|
||||||
|
HRESULT SetAttribs(const WCHAR * pszReqAttribs, const WCHAR * pszOptAttribs);
|
||||||
|
|
||||||
|
HRESULT AddTokens(ULONG cTokens, ISpObjectToken ** pToken);
|
||||||
|
HRESULT AddTokensFromDataKey(ISpDataKey * pDataKey, const WCHAR * pszSubKey, const WCHAR * pszCategoryId);
|
||||||
|
HRESULT AddTokensFromTokenEnum(IEnumSpObjectTokens * pTokenEnum);
|
||||||
|
|
||||||
|
HRESULT Sort(const WCHAR * pszTokenIdToListFirst);
|
||||||
|
};
|
||||||
|
|
||||||
|
//--- Handles for SR grammars and results
|
||||||
|
cpp_quote("#if 0")
|
||||||
|
typedef void * SPWORDHANDLE;
|
||||||
|
typedef void * SPRULEHANDLE;
|
||||||
|
typedef void * SPGRAMMARHANDLE;
|
||||||
|
typedef void * SPRECOCONTEXTHANDLE;
|
||||||
|
typedef void * SPPHRASERULEHANDLE;
|
||||||
|
typedef void * SPPHRASEPROPERTYHANDLE;
|
||||||
|
typedef void * SPTRANSITIONID;
|
||||||
|
cpp_quote("#else")
|
||||||
|
cpp_quote("DECLARE_HANDLE(SPWORDHANDLE);")
|
||||||
|
cpp_quote("DECLARE_HANDLE(SPRULEHANDLE);")
|
||||||
|
cpp_quote("DECLARE_HANDLE(SPGRAMMARHANDLE);")
|
||||||
|
cpp_quote("DECLARE_HANDLE(SPRECOCONTEXTHANDLE);")
|
||||||
|
cpp_quote("DECLARE_HANDLE(SPPHRASERULEHANDLE);")
|
||||||
|
cpp_quote("DECLARE_HANDLE(SPPHRASEPROPERTYHANDLE);")
|
||||||
|
cpp_quote("DECLARE_HANDLE(SPTRANSITIONID);")
|
||||||
|
cpp_quote("#endif")
|
||||||
|
|
||||||
|
|
||||||
|
//--- ISpErrorLog -----------------------------------------------------------
|
||||||
|
// This interface is used to log error information.
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(F4711347-E608-11d2-A086-00C04F8EF9B5),
|
||||||
|
helpstring("ISpErrorLog Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpErrorLog : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT AddError(
|
||||||
|
const long lLineNumber,
|
||||||
|
HRESULT hr,
|
||||||
|
const WCHAR * pszDescription,
|
||||||
|
const WCHAR * pszHelpFile,
|
||||||
|
DWORD dwHelpContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
//--- ISpGrammarCompiler ----------------------------------------------------
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(B1E29D58-A675-11D2-8302-00C04F8EE6C0),
|
||||||
|
helpstring("ISpGrammarCompiler Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpGrammarCompiler : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT CompileStream(
|
||||||
|
IStream * pSource,
|
||||||
|
IStream * pDest,
|
||||||
|
IStream * pHeader,
|
||||||
|
IUnknown * pReserved,
|
||||||
|
ISpErrorLog * pErrorLog,
|
||||||
|
[in] DWORD dwFlags);
|
||||||
|
};
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(3DDCA27C-665C-4786-9F97-8C90C3488B61),
|
||||||
|
helpstring("ISpGramCompBackend Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpGramCompBackend : ISpGrammarBuilder
|
||||||
|
{
|
||||||
|
HRESULT SetSaveObjects(IStream * pStream, ISpErrorLog * pErrorLog);
|
||||||
|
|
||||||
|
HRESULT InitFromBinaryGrammar(const SPBINARYGRAMMAR * pBinaryData);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--- ISpITNProcessor ----------------------------------------------------------
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(12D7360F-A1C9-11d3-BC90-00C04F72DF9F),
|
||||||
|
helpstring("ISpITNProcessor Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
local,
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpITNProcessor : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT LoadITNGrammar(WCHAR *pszCLSID);
|
||||||
|
HRESULT ITNPhrase(ISpPhraseBuilder *pPhrase);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(88A3342A-0BED-4834-922B-88D43173162F),
|
||||||
|
local,
|
||||||
|
helpstring("ISpPhraseBuilder Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpPhraseBuilder : ISpPhrase
|
||||||
|
{
|
||||||
|
HRESULT InitFromPhrase(const SPPHRASE * pPhrase);
|
||||||
|
HRESULT InitFromSerializedPhrase(const SPSERIALIZEDPHRASE * pPhrase);
|
||||||
|
HRESULT AddElements(ULONG cElements, const SPPHRASEELEMENT *pElement);
|
||||||
|
HRESULT AddRules(const SPPHRASERULEHANDLE hParent, const SPPHRASERULE * pRule, SPPHRASERULEHANDLE * phNewRule);
|
||||||
|
HRESULT AddProperties(const SPPHRASEPROPERTYHANDLE hParent, const SPPHRASEPROPERTY * pProperty, SPPHRASEPROPERTYHANDLE * phNewProperty);
|
||||||
|
HRESULT AddReplacements(ULONG cReplacements, const SPPHRASEREPLACEMENT * pReplacements);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--- ISpTask ---------------------------------------------------------------
|
||||||
|
|
||||||
|
cpp_quote("#if defined(__cplusplus)")
|
||||||
|
cpp_quote("interface ISpTask")
|
||||||
|
cpp_quote("{")
|
||||||
|
cpp_quote("virtual HRESULT STDMETHODCALLTYPE Execute(")
|
||||||
|
cpp_quote(" void *pvTaskData,")
|
||||||
|
cpp_quote(" volatile const BOOL* pfContinueProcessing) = 0;")
|
||||||
|
cpp_quote("};")
|
||||||
|
cpp_quote("#else")
|
||||||
|
typedef void * ISpTask;
|
||||||
|
cpp_quote("#endif")
|
||||||
|
|
||||||
|
//--- ISpThreadTask ---------------------------------------------------------
|
||||||
|
|
||||||
|
cpp_quote("#if defined(__cplusplus)")
|
||||||
|
cpp_quote("interface ISpThreadTask")
|
||||||
|
cpp_quote("{")
|
||||||
|
cpp_quote("virtual HRESULT STDMETHODCALLTYPE InitThread(")
|
||||||
|
cpp_quote(" void * pvTaskData,")
|
||||||
|
cpp_quote(" HWND hwnd) = 0;")
|
||||||
|
cpp_quote("virtual HRESULT STDMETHODCALLTYPE ThreadProc(")
|
||||||
|
cpp_quote(" void *pvTaskData,")
|
||||||
|
cpp_quote(" HANDLE hExitThreadEvent,")
|
||||||
|
cpp_quote(" HANDLE hNotifyEvent,")
|
||||||
|
cpp_quote(" HWND hwndWorker,")
|
||||||
|
cpp_quote(" volatile const BOOL * pfContinueProcessing) = 0;")
|
||||||
|
cpp_quote("virtual LRESULT STDMETHODCALLTYPE WindowMessage(")
|
||||||
|
cpp_quote(" void *pvTaskData,")
|
||||||
|
cpp_quote(" HWND hWnd,")
|
||||||
|
cpp_quote(" UINT Msg,")
|
||||||
|
cpp_quote(" WPARAM wParam,")
|
||||||
|
cpp_quote(" LPARAM lParam) = 0;")
|
||||||
|
cpp_quote("};")
|
||||||
|
cpp_quote("#else")
|
||||||
|
typedef void * ISpThreadTask;
|
||||||
|
cpp_quote("#endif")
|
||||||
|
|
||||||
|
//--- ISpThreadControl ------------------------------------------------------
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(A6BE4D73-4403-4358-B22D-0346E23B1764),
|
||||||
|
helpstring("ISpThreadControl Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
local,
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpThreadControl : ISpNotifySink
|
||||||
|
{
|
||||||
|
HRESULT StartThread(DWORD dwFlags, HWND * phwnd);
|
||||||
|
HRESULT WaitForThreadDone(
|
||||||
|
BOOL fForceStop,
|
||||||
|
HRESULT * phrThreadResult,
|
||||||
|
ULONG msTimeOut);
|
||||||
|
HRESULT TerminateThread(void);
|
||||||
|
HANDLE ThreadHandle(void);
|
||||||
|
DWORD ThreadId(void);
|
||||||
|
HANDLE NotifyEvent(void);
|
||||||
|
HWND WindowHandle(void);
|
||||||
|
HANDLE ThreadCompleteEvent(void);
|
||||||
|
HANDLE ExitThreadEvent(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
//--- ISpTaskManager --------------------------------------------------------
|
||||||
|
// This interface is used to implement a task managment service provider
|
||||||
|
// to optimize thread usage.
|
||||||
|
|
||||||
|
typedef [restricted] struct SPTMTHREADINFO
|
||||||
|
{
|
||||||
|
long lPoolSize; // Number of threads in pool (-1 default)
|
||||||
|
long lPriority; // Priority of threads in pool
|
||||||
|
ULONG ulConcurrencyLimit; // Number of threads allowed to concurrently execute (0 default)
|
||||||
|
ULONG ulMaxQuickAllocThreads; // Maximum number of dedicated threads retained
|
||||||
|
} SPTMTHREADINFO;
|
||||||
|
|
||||||
|
[
|
||||||
|
local,
|
||||||
|
uuid(2BAEEF81-2CA3-4331-98F3-26EC5ABEFB03),
|
||||||
|
helpstring("ISpTaskManager Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpTaskManager : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT SetThreadPoolInfo([in] const SPTMTHREADINFO* pPoolInfo);
|
||||||
|
HRESULT GetThreadPoolInfo([out] SPTMTHREADINFO* pPoolInfo);
|
||||||
|
|
||||||
|
HRESULT QueueTask(
|
||||||
|
[in] ISpTask* pTask,
|
||||||
|
[in] void* pvTaskData,
|
||||||
|
[in] HANDLE hCompEvent,
|
||||||
|
[in, out] DWORD* pdwGroupId,
|
||||||
|
[out] DWORD* pTaskID);
|
||||||
|
HRESULT CreateReoccurringTask(
|
||||||
|
[in] ISpTask* pTask,
|
||||||
|
[in] void* pvTaskData,
|
||||||
|
[in] HANDLE hCompEvent,
|
||||||
|
[out] ISpNotifySink** ppTaskCtrl);
|
||||||
|
HRESULT CreateThreadControl(
|
||||||
|
[in] ISpThreadTask* pTask,
|
||||||
|
[in] void* pvTaskData,
|
||||||
|
[in] long nPriority,
|
||||||
|
[out] ISpThreadControl** ppTaskCtrl);
|
||||||
|
|
||||||
|
HRESULT TerminateTask([in] DWORD dwTaskId, [in] ULONG ulWaitPeriod);
|
||||||
|
HRESULT TerminateTaskGroup([in] DWORD dwGroupId, [in] ULONG ulWaitPeriod);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--- ISpTTSEngineSite ------------------------------------------------------
|
||||||
|
|
||||||
|
typedef enum SPVSKIPTYPE
|
||||||
|
{
|
||||||
|
SPVST_SENTENCE = (1L << 0) // Skip sentences
|
||||||
|
} SPVSKIPTYPE;
|
||||||
|
|
||||||
|
typedef enum SPVESACTIONS
|
||||||
|
{
|
||||||
|
SPVES_CONTINUE = 0,
|
||||||
|
SPVES_ABORT = ( 1L << 0 ),
|
||||||
|
SPVES_SKIP = ( 1L << 1 ),
|
||||||
|
SPVES_RATE = ( 1L << 2 ),
|
||||||
|
SPVES_VOLUME = ( 1L << 3 )
|
||||||
|
} SPVESACTIONS;
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
local,
|
||||||
|
uuid(9880499B-CCE9-11d2-B503-00C04F797396),
|
||||||
|
helpstring("ISpTTSEngineSite Interface"),
|
||||||
|
pointer_default(unique)
|
||||||
|
]
|
||||||
|
interface ISpTTSEngineSite : ISpEventSink
|
||||||
|
{
|
||||||
|
DWORD GetActions( void );
|
||||||
|
HRESULT Write( [in]const void* pBuff, [in]ULONG cb, [out]ULONG *pcbWritten );
|
||||||
|
HRESULT GetRate( [out]long* pRateAdjust );
|
||||||
|
HRESULT GetVolume( [out]USHORT* pusVolume );
|
||||||
|
HRESULT GetSkipInfo( [out]SPVSKIPTYPE* peType, [out]long* plNumItems );
|
||||||
|
HRESULT CompleteSkip( [in]long ulNumSkipped );
|
||||||
|
};
|
||||||
|
|
||||||
|
//--- ISpTTSEngine ----------------------------------------------------------
|
||||||
|
|
||||||
|
typedef struct SPVTEXTFRAG
|
||||||
|
{
|
||||||
|
struct SPVTEXTFRAG* pNext; // Next text fragment in list, NULL == end of list
|
||||||
|
SPVSTATE State; // Current XML attribute state
|
||||||
|
LPCWSTR pTextStart;
|
||||||
|
ULONG ulTextLen;
|
||||||
|
ULONG ulTextSrcOffset; // Original source position of the fragment text
|
||||||
|
} SPVTEXTFRAG;
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
local,
|
||||||
|
uuid(A74D7C8E-4CC5-4f2f-A6EB-804DEE18500E),
|
||||||
|
helpstring("ISpTTSEngine Interface"),
|
||||||
|
pointer_default(unique)
|
||||||
|
]
|
||||||
|
interface ISpTTSEngine : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT Speak( [in]DWORD dwSpeakFlags,
|
||||||
|
[in]REFGUID rguidFormatId, [in]const WAVEFORMATEX * pWaveFormatEx,
|
||||||
|
[in]const SPVTEXTFRAG* pTextFragList, [in]ISpTTSEngineSite* pOutputSite );
|
||||||
|
HRESULT GetOutputFormat( [in] const GUID * pTargetFmtId, [in] const WAVEFORMATEX * pTargetWaveFormatEx,
|
||||||
|
[out] GUID * pOutputFormatId, [out] WAVEFORMATEX ** ppCoMemOutputWaveFormatEx);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--- SR Engine data structures ----------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
typedef [restricted] struct SPWORDENTRY
|
||||||
|
{
|
||||||
|
SPWORDHANDLE hWord;
|
||||||
|
LANGID LangID;
|
||||||
|
WCHAR * pszDisplayText;
|
||||||
|
WCHAR * pszLexicalForm;
|
||||||
|
SPPHONEID * aPhoneId;
|
||||||
|
void * pvClientContext;
|
||||||
|
} SPWORDENTRY;
|
||||||
|
|
||||||
|
typedef [restricted] struct SPRULEENTRY
|
||||||
|
{
|
||||||
|
SPRULEHANDLE hRule;
|
||||||
|
SPSTATEHANDLE hInitialState;
|
||||||
|
DWORD Attributes; // SPCFGRULEATTRIBUTES
|
||||||
|
void * pvClientRuleContext;
|
||||||
|
void * pvClientGrammarContext;
|
||||||
|
} SPRULEENTRY;
|
||||||
|
|
||||||
|
typedef enum SPTRANSITIONTYPE
|
||||||
|
{
|
||||||
|
SPTRANSEPSILON,
|
||||||
|
SPTRANSWORD,
|
||||||
|
SPTRANSRULE,
|
||||||
|
SPTRANSTEXTBUF,
|
||||||
|
SPTRANSWILDCARD,
|
||||||
|
SPTRANSDICTATION
|
||||||
|
} SPTRANSITIONTYPE;
|
||||||
|
|
||||||
|
typedef [restricted] struct SPTRANSITIONENTRY
|
||||||
|
{
|
||||||
|
SPTRANSITIONID ID;
|
||||||
|
SPSTATEHANDLE hNextState;
|
||||||
|
BYTE Type; // SPTRANSITIONTYPE
|
||||||
|
char RequiredConfidence;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
DWORD fHasProperty; // Boolean type
|
||||||
|
};
|
||||||
|
float Weight;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
SPSTATEHANDLE hRuleInitialState; // Only if Type == SPTRANSRULE
|
||||||
|
SPRULEHANDLE hRule;
|
||||||
|
void * pvClientRuleContext;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
SPWORDHANDLE hWord; // Only if Type == SPTRANSWORD
|
||||||
|
void * pvClientWordContext;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
void * pvGrammarCookie; // Only if Type == SPTRANSTEXTBUF or SPTRANSWILDCARD or SPTRANSDICTATION
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} SPTRANSITIONENTRY;
|
||||||
|
|
||||||
|
typedef [restricted] struct SPTRANSITIONPROPERTY
|
||||||
|
{
|
||||||
|
const WCHAR * pszName;
|
||||||
|
ULONG ulId;
|
||||||
|
const WCHAR * pszValue;
|
||||||
|
VARIANT vValue; // Will be VT_BOOL, VT_I4, VT_R4, VT_R8, or VT_BYREF (only for dynamic grammars)
|
||||||
|
} SPTRANSITIONPROPERTY;
|
||||||
|
|
||||||
|
typedef [restricted] struct SPSTATEINFO
|
||||||
|
{
|
||||||
|
ULONG cAllocatedEntries;
|
||||||
|
SPTRANSITIONENTRY * pTransitions;
|
||||||
|
ULONG cEpsilons;
|
||||||
|
ULONG cRules;
|
||||||
|
ULONG cWords;
|
||||||
|
ULONG cSpecialTransitions;
|
||||||
|
} SPSTATEINFO;
|
||||||
|
|
||||||
|
typedef [restricted] struct SPPATHENTRY
|
||||||
|
{
|
||||||
|
SPTRANSITIONID hTransition;
|
||||||
|
SPPHRASEELEMENT elem;
|
||||||
|
} SPPATHENTRY;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--- ISpCFGInterpreterSite -------------------------------------------------
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(6A6FFAD8-78B6-473d-B844-98152E4FB16B),
|
||||||
|
helpstring("ISpCFGInterpreterSite Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
local,
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpCFGInterpreterSite : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT AddTextReplacement([in] SPPHRASEREPLACEMENT * pReplace);
|
||||||
|
HRESULT AddProperty([in] const SPPHRASEPROPERTY *pProperty);
|
||||||
|
HRESULT GetResourceValue(
|
||||||
|
[in] const WCHAR *pszResourceName,
|
||||||
|
[out] WCHAR ** ppCoMemResource);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--- ISpCFGInterpreter -----------------------------------------------------
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(F3D3F926-11FC-11d3-BB97-00C04F8EE6C0),
|
||||||
|
helpstring("ISpCFGInterpreter Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
local,
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
interface ISpCFGInterpreter : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT InitGrammar(
|
||||||
|
[in] const WCHAR * pszGrammarName,
|
||||||
|
[in] const void ** pvGrammarData);
|
||||||
|
HRESULT Interpret(
|
||||||
|
[in] ISpPhraseBuilder * pPhrase,
|
||||||
|
[in] const ULONG ulFirstElement,
|
||||||
|
[in] const ULONG ulCountOfElements,
|
||||||
|
[in] ISpCFGInterpreterSite * pSite);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum SPCFGNOTIFY
|
||||||
|
{
|
||||||
|
SPCFGN_ADD,
|
||||||
|
SPCFGN_REMOVE,
|
||||||
|
SPCFGN_INVALIDATE,
|
||||||
|
SPCFGN_ACTIVATE,
|
||||||
|
SPCFGN_DEACTIVATE
|
||||||
|
} SPCFGNOTIFY;
|
||||||
|
|
||||||
|
//--- ISpSREngineSite -------------------------------------------------------
|
||||||
|
|
||||||
|
typedef enum SPRESULTTYPE
|
||||||
|
{
|
||||||
|
SPRT_CFG = 0,
|
||||||
|
SPRT_SLM = 1,
|
||||||
|
SPRT_PROPRIETARY = 2,
|
||||||
|
SPRT_FALSE_RECOGNITION = ( 1L << 2 ) // Flag used to indicate a false recognition
|
||||||
|
} SPRESULTTYPE;
|
||||||
|
|
||||||
|
typedef struct tagSPPHRASEALT
|
||||||
|
{
|
||||||
|
ISpPhraseBuilder * pPhrase;
|
||||||
|
ULONG ulStartElementInParent;
|
||||||
|
ULONG cElementsInParent;
|
||||||
|
ULONG cElementsInAlternate;
|
||||||
|
void * pvAltExtra;
|
||||||
|
ULONG cbAltExtra;
|
||||||
|
} SPPHRASEALT;
|
||||||
|
|
||||||
|
// Result structure passed from engine to SAPI
|
||||||
|
typedef struct SPRECORESULTINFO
|
||||||
|
{
|
||||||
|
ULONG cbSize; // Total size of this structure
|
||||||
|
SPRESULTTYPE eResultType; // Type of result object (CFG, SLM, or Proprietary)
|
||||||
|
BOOL fHypothesis; // If true then this recognition is a hypothesis
|
||||||
|
BOOL fProprietaryAutoPause;// This field is only used for SPERT_PROPRIETARY grammars. If true, recognition will pause.
|
||||||
|
ULONGLONG ullStreamPosStart; // Start and end stream positions of recognition
|
||||||
|
ULONGLONG ullStreamPosEnd;
|
||||||
|
SPGRAMMARHANDLE hGrammar; // Required for SPERT_SLM and SPERT_PROPRIETARY else NULL
|
||||||
|
ULONG ulSizeEngineData; // Size of pvEngineData
|
||||||
|
void * pvEngineData; // Extra engine specific data
|
||||||
|
ISpPhraseBuilder* pPhrase; // Pointer to phrase object
|
||||||
|
SPPHRASEALT* aPhraseAlts; // Alternates array
|
||||||
|
ULONG ulNumAlts; // Number of alternates in the array
|
||||||
|
} SPRECORESULTINFO;
|
||||||
|
|
||||||
|
typedef enum SPWORDINFOOPT
|
||||||
|
{
|
||||||
|
SPWIO_NONE = 0,
|
||||||
|
SPWIO_WANT_TEXT = 1
|
||||||
|
} SPWORDINFOOPT;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum SPRULEINFOOPT
|
||||||
|
{
|
||||||
|
SPRIO_NONE = 0,
|
||||||
|
} SPRULEINFOOPT;
|
||||||
|
|
||||||
|
typedef struct SPPARSEINFO
|
||||||
|
{
|
||||||
|
ULONG cbSize;
|
||||||
|
SPRULEHANDLE hRule;
|
||||||
|
ULONGLONG ullAudioStreamPosition;
|
||||||
|
ULONG ulAudioSize;
|
||||||
|
ULONG cTransitions;
|
||||||
|
SPPATHENTRY * pPath;
|
||||||
|
GUID SREngineID;
|
||||||
|
ULONG ulSREnginePrivateDataSize;
|
||||||
|
const BYTE * pSREnginePrivateData;
|
||||||
|
BOOL fHypothesis;
|
||||||
|
} SPPARSEINFO;
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(3B414AEC-720C-4883-B9EF-178CD394FB3A),
|
||||||
|
helpstring("ISpSREngineSite Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
local
|
||||||
|
]
|
||||||
|
interface ISpSREngineSite : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT Read([in] void * pv, [in] ULONG cb, [out] ULONG * pcbRead);
|
||||||
|
HRESULT DataAvailable(ULONG * pcb);
|
||||||
|
HRESULT SetBufferNotifySize([in] ULONG cbSize);
|
||||||
|
HRESULT ParseFromTransitions([in] const SPPARSEINFO * pParseInfo,
|
||||||
|
[out] ISpPhraseBuilder ** ppNewPhrase);
|
||||||
|
HRESULT Recognition([in] const SPRECORESULTINFO * pResultInfo);
|
||||||
|
HRESULT AddEvent([in] const SPEVENT* pEvent, [in] SPRECOCONTEXTHANDLE hSAPIRecoContext);
|
||||||
|
HRESULT Synchronize([in] ULONGLONG ullProcessedThruPos);
|
||||||
|
HRESULT GetWordInfo([in, out] SPWORDENTRY * pWordEntry, [in] SPWORDINFOOPT Options); // Caller must fill in hWord. if fWantWordText then caller must CoTaskMemFree the pszWord.
|
||||||
|
HRESULT SetWordClientContext(SPWORDHANDLE hWord, void * pvClientContext);
|
||||||
|
HRESULT GetRuleInfo([in, out] SPRULEENTRY * pRuleEntry, [in] SPRULEINFOOPT Options); // Caller must fill in hRule.SPRULEHANDLE hRule, BOOL * pfActive, BOOL *pfAutoPause, SPSTATEHANDLE * phInitialState, void ** ppvClientContext);
|
||||||
|
HRESULT SetRuleClientContext(SPRULEHANDLE hRule, void * pvClientContext);
|
||||||
|
HRESULT GetStateInfo(SPSTATEHANDLE hState, SPSTATEINFO * pStateInfo);
|
||||||
|
HRESULT GetResource( [in] SPRULEHANDLE hRule, [in] const WCHAR *pszResourceName, [out] WCHAR ** ppCoMemResource );
|
||||||
|
HRESULT GetTransitionProperty([in] SPTRANSITIONID ID, [out] SPTRANSITIONPROPERTY **ppCoMemProperty);
|
||||||
|
HRESULT IsAlternate( [in]SPRULEHANDLE hRule, [in]SPRULEHANDLE hAltRule );
|
||||||
|
HRESULT GetMaxAlternates( [in]SPRULEHANDLE hRule, [out]ULONG* pulNumAlts );
|
||||||
|
HRESULT GetContextMaxAlternates( [in] SPRECOCONTEXTHANDLE hContext, [out] ULONG * pulNumAlts);
|
||||||
|
HRESULT UpdateRecoPos([in] ULONGLONG ullCurrentRecoPos);
|
||||||
|
};
|
||||||
|
|
||||||
|
//--- ISpSREngine -----------------------------------------------------------
|
||||||
|
typedef enum SPPROPSRC
|
||||||
|
{
|
||||||
|
SPPROPSRC_RECO_INST,
|
||||||
|
SPPROPSRC_RECO_CTX,
|
||||||
|
SPPROPSRC_RECO_GRAMMAR
|
||||||
|
} SPPROPSRC;
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(2F472991-854B-4465-B613-FBAFB3AD8ED8),
|
||||||
|
helpstring("ISpSREngine Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
local
|
||||||
|
]
|
||||||
|
interface ISpSREngine : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT SetSite([in] ISpSREngineSite *pSite);
|
||||||
|
|
||||||
|
HRESULT GetInputAudioFormat(
|
||||||
|
[in] const GUID * pguidSourceFormatId,
|
||||||
|
[in] const WAVEFORMATEX * pSourceWaveFormatEx,
|
||||||
|
[out] GUID * pguidDesiredFormatId,
|
||||||
|
[out] WAVEFORMATEX ** ppCoMemDesiredWaveFormatEx);
|
||||||
|
|
||||||
|
HRESULT RecognizeStream([in] REFGUID rguidFmtId, [in] const WAVEFORMATEX * pWaveFormatEx,
|
||||||
|
[in] HANDLE hRequestSync, [in] HANDLE hDataAvailable,
|
||||||
|
[in] HANDLE hExit, [in] BOOL fNewAudioStream, [in] BOOL fRealTimeAudio,
|
||||||
|
[in] ISpObjectToken * pAudioObjectToken);
|
||||||
|
|
||||||
|
HRESULT SetRecoProfile(ISpObjectToken * pProfile);
|
||||||
|
|
||||||
|
HRESULT OnCreateGrammar([in] void * pvEngineRecoContext,
|
||||||
|
[in] SPGRAMMARHANDLE hSAPIGrammar,
|
||||||
|
[out] void ** ppvEngineGrammarContext);
|
||||||
|
|
||||||
|
HRESULT OnDeleteGrammar([in] void * pvEngineGrammar);
|
||||||
|
|
||||||
|
HRESULT LoadProprietaryGrammar(
|
||||||
|
[in] void * pvEngineGrammar,
|
||||||
|
[in] REFGUID rguidParam,
|
||||||
|
[in, string] const WCHAR * pszStringParam,
|
||||||
|
[in] const void * pvDataParam,
|
||||||
|
[in] ULONG ulDataSize,
|
||||||
|
[in] SPLOADOPTIONS Options); // Note for SAPI 5.0 this is always SPLO_NONE
|
||||||
|
|
||||||
|
HRESULT UnloadProprietaryGrammar([in] void * pvEngineGrammar);
|
||||||
|
|
||||||
|
HRESULT SetProprietaryRuleState([in] void * pvEngineGrammar,
|
||||||
|
[in, string] const WCHAR * pszName,
|
||||||
|
[in] void * pReserved,
|
||||||
|
[in] SPRULESTATE NewState,
|
||||||
|
[out] ULONG * pcRulesChanged);
|
||||||
|
HRESULT SetProprietaryRuleIdState([in] void * pvEngineGrammar,
|
||||||
|
[in] DWORD dwRuleId,
|
||||||
|
[in] SPRULESTATE NewState);
|
||||||
|
HRESULT LoadSLM([in] void * pvEngineGrammar, [in, string] const WCHAR * pszTopicName);
|
||||||
|
HRESULT UnloadSLM([in] void * pvEngineGrammar);
|
||||||
|
HRESULT SetSLMState([in] void * pvEngineGrammar, [in] SPRULESTATE NewState);
|
||||||
|
HRESULT SetWordSequenceData([in] void * pvEngineGrammar, [in] const WCHAR * pText, [in] ULONG cchText, [in] const SPTEXTSELECTIONINFO * pInfo);
|
||||||
|
HRESULT SetTextSelection([in] void * pvEngineGrammar, [in] const SPTEXTSELECTIONINFO * pInfo);
|
||||||
|
HRESULT IsPronounceable([in] void * pvEngineGrammar, [in, string] const WCHAR * pszWord, [out] SPWORDPRONOUNCEABLE *pWordPronounceable);
|
||||||
|
|
||||||
|
HRESULT OnCreateRecoContext(
|
||||||
|
[in] SPRECOCONTEXTHANDLE hSAPIRecoContext,
|
||||||
|
[out] void ** ppvEngineContext);
|
||||||
|
HRESULT OnDeleteRecoContext([in] void * pvEngineContext);
|
||||||
|
|
||||||
|
HRESULT PrivateCall([in] void * pvEngineContext, [in, out] PVOID pCallFrame, [in] ULONG ulCallFrameSize);
|
||||||
|
|
||||||
|
HRESULT SetAdaptationData([in] void * pvEngineContext, const WCHAR *pAdaptationData, const ULONG cch);
|
||||||
|
|
||||||
|
HRESULT SetPropertyNum( [in]SPPROPSRC eSrc, [in]void* pvSrcObj,
|
||||||
|
[in]const WCHAR* pName, [in]LONG lValue );
|
||||||
|
HRESULT GetPropertyNum( [in]SPPROPSRC eSrc, [in]void* pvSrcObj,
|
||||||
|
[in]const WCHAR* pName, [out]LONG* lValue );
|
||||||
|
HRESULT SetPropertyString( [in]SPPROPSRC eSrc, [in]void* pvSrcObj,
|
||||||
|
[in]const WCHAR* pName, [in]const WCHAR* pValue );
|
||||||
|
HRESULT GetPropertyString( [in]SPPROPSRC eSrc, [in]void* pvSrcObj,
|
||||||
|
[in]const WCHAR* pName, [out]WCHAR** ppCoMemValue );
|
||||||
|
|
||||||
|
HRESULT SetGrammarState([in] void * pvEngineGrammar, [in] SPGRAMMARSTATE eGrammarState);
|
||||||
|
|
||||||
|
HRESULT WordNotify(SPCFGNOTIFY Action, ULONG cWords, const SPWORDENTRY * pWords);
|
||||||
|
HRESULT RuleNotify(SPCFGNOTIFY Action, ULONG cRules, const SPRULEENTRY * pRules);
|
||||||
|
|
||||||
|
HRESULT PrivateCallEx([in] void * pvEngineContext, [in] const void * pInCallFrame, [in] ULONG ulInCallFrameSize,
|
||||||
|
[out] void ** ppvCoMemResponse, [out] ULONG * pulResponseSize);
|
||||||
|
|
||||||
|
HRESULT SetContextState([in] void * pvEngineContext, [in] SPCONTEXTSTATE eContextState);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--- ISpSRAlternates
|
||||||
|
|
||||||
|
typedef struct tagSPPHRASEALTREQUEST
|
||||||
|
{
|
||||||
|
ULONG ulStartElement;
|
||||||
|
ULONG cElements;
|
||||||
|
ULONG ulRequestAltCount;
|
||||||
|
|
||||||
|
void * pvResultExtra;
|
||||||
|
ULONG cbResultExtra;
|
||||||
|
|
||||||
|
ISpPhrase * pPhrase;
|
||||||
|
ISpRecoContext * pRecoContext;
|
||||||
|
} SPPHRASEALTREQUEST;
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(FECE8294-2BE1-408f-8E68-2DE377092F0E),
|
||||||
|
helpstring("ISpSRAlternates Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
local
|
||||||
|
]
|
||||||
|
interface ISpSRAlternates : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT GetAlternates([in] SPPHRASEALTREQUEST * pAltRequest,
|
||||||
|
[out] SPPHRASEALT **ppAlts,
|
||||||
|
[out] ULONG *pcAlts);
|
||||||
|
HRESULT Commit([in] SPPHRASEALTREQUEST * pAltRequest,
|
||||||
|
[in] SPPHRASEALT * pAlt,
|
||||||
|
[out] void **ppvResultExtra,
|
||||||
|
[out] ULONG *pcbResultExtra);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface used by engine specific recoctxt extension object to call into engine
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(8E7C791E-4467-11d3-9723-00C04F72DB08),
|
||||||
|
helpstring("_ISpPrivateEngineCall Interface"),
|
||||||
|
pointer_default(unique),
|
||||||
|
local
|
||||||
|
]
|
||||||
|
interface _ISpPrivateEngineCall : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT CallEngine([in, out] void * pCallFrame, [in] ULONG ulCallFrameSize);
|
||||||
|
HRESULT CallEngineEx([in] const void * pInFrame, [in] ULONG ulInFrameSize,
|
||||||
|
[out] void ** ppCoMemOutFrame, [out] ULONG * pulOutFrameSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//--- CoClass definitions ---------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
[
|
||||||
|
helpstring("Microsoft Speech Object DDK Library"),
|
||||||
|
uuid(9903F14C-12CE-4c99-9986-2EE3D7D588A8),
|
||||||
|
version(5.0)
|
||||||
|
]
|
||||||
|
library SpeechDDKLib
|
||||||
|
{
|
||||||
|
importlib("stdole32.tlb");
|
||||||
|
importlib("stdole2.tlb");
|
||||||
|
|
||||||
|
//--- SpDataKey ---------------------------------------------------------
|
||||||
|
[
|
||||||
|
uuid(D9F6EE60-58C9-458b-88E1-2F908FD7F87C),
|
||||||
|
helpstring("Data Key")
|
||||||
|
]
|
||||||
|
coclass SpDataKey
|
||||||
|
{
|
||||||
|
interface ISpRegDataKey;
|
||||||
|
[default] interface ISpDataKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- SpObjectTokenEnum --------------------------------------------------
|
||||||
|
[
|
||||||
|
uuid(3918D75F-0ACB-41f2-B733-92AA15BCECF6),
|
||||||
|
helpstring("Object Token Enumerator")
|
||||||
|
]
|
||||||
|
coclass SpObjectTokenEnum
|
||||||
|
{
|
||||||
|
interface ISpObjectTokenEnumBuilder;
|
||||||
|
[default] interface IEnumSpObjectTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- SpPhraseBuilder ---------------------------------------------------
|
||||||
|
[
|
||||||
|
uuid(777B6BBD-2FF2-11d3-88FE-00C04F8EF9B5),
|
||||||
|
helpstring("Phrase Builder Class")
|
||||||
|
]
|
||||||
|
coclass SpPhraseBuilder
|
||||||
|
{
|
||||||
|
[default] interface ISpPhraseBuilder;
|
||||||
|
}
|
||||||
|
//--- SpITNProcessor ----------------------------------------------------
|
||||||
|
[
|
||||||
|
uuid(12D73610-A1C9-11d3-BC90-00C04F72DF9F),
|
||||||
|
helpstring("SpITNProcessor Class"),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
coclass SpITNProcessor
|
||||||
|
{
|
||||||
|
[default] interface ISpITNProcessor;
|
||||||
|
};
|
||||||
|
//--- SpGrammarCompiler ---------------------------------------------
|
||||||
|
[
|
||||||
|
uuid(B1E29D59-A675-11D2-8302-00C04F8EE6C0),
|
||||||
|
helpstring("Microsoft Speech Grammar Compiler")
|
||||||
|
]
|
||||||
|
coclass SpGrammarCompiler
|
||||||
|
{
|
||||||
|
[default] interface ISpGrammarCompiler;
|
||||||
|
};
|
||||||
|
|
||||||
|
//--- SpGramCompBackend ---------------------------------------------
|
||||||
|
[
|
||||||
|
uuid(DA93E903-C843-11D2-A084-00C04F8EF9B5),
|
||||||
|
helpstring("Grammar Class"),
|
||||||
|
restricted
|
||||||
|
]
|
||||||
|
coclass SpGramCompBackend
|
||||||
|
{
|
||||||
|
[default] interface ISpGramCompBackend;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
854
mp/src/utils/sapi51/Include/Spddkhlp.h
Normal file
854
mp/src/utils/sapi51/Include/Spddkhlp.h
Normal file
@ -0,0 +1,854 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* SPDDKHLP.h *
|
||||||
|
*------------*
|
||||||
|
* Description:
|
||||||
|
* This is the header file for core helper functions implementation.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
*******************************************************************************/
|
||||||
|
#ifndef SPDDKHLP_h
|
||||||
|
#define SPDDKHLP_h
|
||||||
|
|
||||||
|
#ifndef SPHelper_h
|
||||||
|
#include <sphelper.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sapiddk.h>
|
||||||
|
|
||||||
|
#ifndef SPError_h
|
||||||
|
#include <SPError.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPDebug_h
|
||||||
|
#include <SPDebug.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _INC_LIMITS
|
||||||
|
#include <limits.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _INC_CRTDBG
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _INC_MALLOC
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _INC_MMSYSTEM
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __comcat_h__
|
||||||
|
#include <comcat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=== Constants ==============================================================
|
||||||
|
#define sp_countof(x) ((sizeof(x) / sizeof(*(x))))
|
||||||
|
|
||||||
|
#define SP_IS_BAD_WRITE_PTR(p) ( SPIsBadWritePtr( p, sizeof(*(p)) ))
|
||||||
|
#define SP_IS_BAD_READ_PTR(p) ( SPIsBadReadPtr( p, sizeof(*(p)) ))
|
||||||
|
#define SP_IS_BAD_CODE_PTR(p) ( ::IsBadCodePtr((FARPROC)(p) )
|
||||||
|
#define SP_IS_BAD_INTERFACE_PTR(p) ( SPIsBadInterfacePtr( (p) ) )
|
||||||
|
#define SP_IS_BAD_VARIANT_PTR(p) ( SPIsBadVARIANTPtr( (p) ) )
|
||||||
|
#define SP_IS_BAD_STRING_PTR(p) ( SPIsBadStringPtr( (p) ) )
|
||||||
|
|
||||||
|
#define SP_IS_BAD_OPTIONAL_WRITE_PTR(p) ((p) && SPIsBadWritePtr( p, sizeof(*(p)) ))
|
||||||
|
#define SP_IS_BAD_OPTIONAL_READ_PTR(p) ((p) && SPIsBadReadPtr( p, sizeof(*(p)) ))
|
||||||
|
#define SP_IS_BAD_OPTIONAL_INTERFACE_PTR(p) ((p) && SPIsBadInterfacePtr(p))
|
||||||
|
#define SP_IS_BAD_OPTIONAL_STRING_PTR(p) ((p) && SPIsBadStringPtr(p))
|
||||||
|
|
||||||
|
//=== Class, Enum, Struct, Template, and Union Declarations ==================
|
||||||
|
|
||||||
|
//=== Inlines ================================================================
|
||||||
|
|
||||||
|
/*** Pointer validation functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Add decent debug output for bad parameters
|
||||||
|
|
||||||
|
inline BOOL SPIsBadStringPtr( const WCHAR * psz, ULONG cMaxChars = 0xFFFF )
|
||||||
|
{
|
||||||
|
BOOL IsBad = false;
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if( *psz++ == 0 ) return IsBad;
|
||||||
|
}
|
||||||
|
while( --cMaxChars );
|
||||||
|
}
|
||||||
|
__except( GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION )
|
||||||
|
{
|
||||||
|
IsBad = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsBad;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BOOL SPIsBadReadPtr( const void* pMem, UINT Size )
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
BOOL bIsBad = ::IsBadReadPtr( pMem, Size );
|
||||||
|
SPDBG_ASSERT(!bIsBad);
|
||||||
|
return bIsBad;
|
||||||
|
#else
|
||||||
|
return ::IsBadReadPtr( pMem, Size );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BOOL SPIsBadWritePtr( void* pMem, UINT Size )
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
BOOL bIsBad = ::IsBadWritePtr( pMem, Size );
|
||||||
|
SPDBG_ASSERT(!bIsBad);
|
||||||
|
return bIsBad;
|
||||||
|
#else
|
||||||
|
return ::IsBadWritePtr( pMem, Size );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BOOL SPIsBadInterfacePtr( const IUnknown* pUnknown )
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
BOOL bIsBad = ( ::IsBadReadPtr( pUnknown, sizeof( *pUnknown ) ) ||
|
||||||
|
::IsBadCodePtr( (FARPROC)((void**)pUnknown)[0] ))?
|
||||||
|
(true):(false);
|
||||||
|
SPDBG_ASSERT(!bIsBad);
|
||||||
|
return bIsBad;
|
||||||
|
#else
|
||||||
|
return ( ::IsBadReadPtr( pUnknown, sizeof( *pUnknown ) ) ||
|
||||||
|
::IsBadCodePtr( (FARPROC)((void**)pUnknown)[0] ))?
|
||||||
|
(true):(false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BOOL SPIsBadVARIANTPtr( const VARIANT* pVar )
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
BOOL bIsBad = ::IsBadReadPtr( pVar, sizeof( *pVar ) );
|
||||||
|
SPDBG_ASSERT(!bIsBad);
|
||||||
|
return bIsBad;
|
||||||
|
#else
|
||||||
|
return ::IsBadReadPtr( pVar, sizeof( *pVar ) );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __ATLCOM_H__ //--- Only enable these if ATL is being used
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper functions can be used to implement GetObjectToken/SetObjectToken for objects that
|
||||||
|
// support ISpObjectWithToken
|
||||||
|
//
|
||||||
|
inline HRESULT SpGenericSetObjectToken(ISpObjectToken * pCallersToken, CComPtr<ISpObjectToken> & cpObjToken)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (SP_IS_BAD_INTERFACE_PTR(pCallersToken))
|
||||||
|
{
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cpObjToken)
|
||||||
|
{
|
||||||
|
hr = SPERR_ALREADY_INITIALIZED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cpObjToken = pCallersToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline HRESULT SpGenericGetObjectToken(ISpObjectToken ** ppCallersToken, CComPtr<ISpObjectToken> & cpObjToken)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (SP_IS_BAD_WRITE_PTR(ppCallersToken))
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppCallersToken = cpObjToken;
|
||||||
|
if (*ppCallersToken)
|
||||||
|
{
|
||||||
|
(*ppCallersToken)->AddRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = S_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __ATLCOM_H__
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper class for SPSTATEINFO sturcture automatically initializes and cleans up
|
||||||
|
// the structure + provides a few helper functions.
|
||||||
|
//
|
||||||
|
class CSpStateInfo : public SPSTATEINFO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSpStateInfo()
|
||||||
|
{
|
||||||
|
cAllocatedEntries = NULL;
|
||||||
|
pTransitions = NULL;
|
||||||
|
}
|
||||||
|
~CSpStateInfo()
|
||||||
|
{
|
||||||
|
::CoTaskMemFree(pTransitions);
|
||||||
|
}
|
||||||
|
SPTRANSITIONENTRY * FirstEpsilon()
|
||||||
|
{
|
||||||
|
return pTransitions;
|
||||||
|
}
|
||||||
|
SPTRANSITIONENTRY * FirstRule()
|
||||||
|
{
|
||||||
|
return pTransitions + cEpsilons;
|
||||||
|
}
|
||||||
|
SPTRANSITIONENTRY * FirstWord()
|
||||||
|
{
|
||||||
|
return pTransitions + cEpsilons + cRules;
|
||||||
|
}
|
||||||
|
SPTRANSITIONENTRY * FirstSpecialTransition()
|
||||||
|
{
|
||||||
|
return pTransitions + cEpsilons + cRules + cWords;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// This basic queue implementation can be used to maintin linked lists of classes. The class T
|
||||||
|
// must contain the member m_pNext which is used by this template to point to the next element.
|
||||||
|
// If the bPurgeWhenDeleted is TRUE then all of the elements in the queue will be deleted
|
||||||
|
// when the queue is deleted, otherwise they will not.
|
||||||
|
// If bMaintainCount is TRUE then a running count will be maintained, and GetCount() will be
|
||||||
|
// efficent. If it is FALSE then a running count will not be maintained, and GetCount() will
|
||||||
|
// be an order N operation. If you do not require a count, then
|
||||||
|
//
|
||||||
|
|
||||||
|
template <class T, BOOL bPurgeWhenDeleted> class CSpBasicList;
|
||||||
|
|
||||||
|
template <class T, BOOL bPurgeWhenDeleted = TRUE, BOOL bMaintainCount = FALSE>
|
||||||
|
class CSpBasicQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T * m_pHead;
|
||||||
|
T * m_pTail;
|
||||||
|
ULONG m_cElements; // Warning! Use GetCount() -- Not maintained if bMaintainCount is FALSE.
|
||||||
|
|
||||||
|
CSpBasicQueue()
|
||||||
|
{
|
||||||
|
m_pHead = NULL;
|
||||||
|
if (bMaintainCount)
|
||||||
|
{
|
||||||
|
m_cElements = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~CSpBasicQueue()
|
||||||
|
{
|
||||||
|
if (bPurgeWhenDeleted)
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CreateNode(T ** ppNode)
|
||||||
|
{
|
||||||
|
*ppNode = new T;
|
||||||
|
if (*ppNode)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T * GetNext(const T * pNode)
|
||||||
|
{
|
||||||
|
return pNode->m_pNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
T * Item(ULONG i)
|
||||||
|
{
|
||||||
|
T * pNode = m_pHead;
|
||||||
|
while (pNode && i)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
pNode = pNode->m_pNext;
|
||||||
|
}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertAfter(T * pPrev, T * pNewNode)
|
||||||
|
{
|
||||||
|
if (pPrev)
|
||||||
|
{
|
||||||
|
pNewNode->m_pNext = pPrev->m_pNext;
|
||||||
|
pPrev->m_pNext = pNewNode;
|
||||||
|
if (pNewNode->m_pNext == NULL)
|
||||||
|
{
|
||||||
|
m_pTail = pNewNode;
|
||||||
|
}
|
||||||
|
if (bMaintainCount) ++m_cElements;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InsertHead(pNewNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertTail(T * pNode)
|
||||||
|
{
|
||||||
|
pNode->m_pNext = NULL;
|
||||||
|
if (m_pHead)
|
||||||
|
{
|
||||||
|
m_pTail->m_pNext = pNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pHead = pNode;
|
||||||
|
}
|
||||||
|
m_pTail = pNode;
|
||||||
|
if (bMaintainCount) ++m_cElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertHead(T * pNode)
|
||||||
|
{
|
||||||
|
pNode->m_pNext = m_pHead;
|
||||||
|
if (m_pHead == NULL)
|
||||||
|
{
|
||||||
|
m_pTail = pNode;
|
||||||
|
}
|
||||||
|
m_pHead = pNode;
|
||||||
|
if (bMaintainCount) ++m_cElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * RemoveHead()
|
||||||
|
{
|
||||||
|
T * pNode = m_pHead;
|
||||||
|
if (pNode)
|
||||||
|
{
|
||||||
|
m_pHead = pNode->m_pNext;
|
||||||
|
if (bMaintainCount) --m_cElements;
|
||||||
|
}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * RemoveTail()
|
||||||
|
{
|
||||||
|
T * pNode = m_pHead;
|
||||||
|
if (pNode)
|
||||||
|
{
|
||||||
|
if (pNode == m_pTail)
|
||||||
|
{
|
||||||
|
m_pHead = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T * pPrev;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pPrev = pNode;
|
||||||
|
pNode = pNode->m_pNext;
|
||||||
|
} while ( pNode != m_pTail );
|
||||||
|
pPrev->m_pNext = NULL;
|
||||||
|
m_pTail = pPrev;
|
||||||
|
}
|
||||||
|
if (bMaintainCount) --m_cElements;
|
||||||
|
}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge()
|
||||||
|
{
|
||||||
|
while (m_pHead)
|
||||||
|
{
|
||||||
|
T * pDie = m_pHead;
|
||||||
|
m_pHead = pDie->m_pNext;
|
||||||
|
delete pDie;
|
||||||
|
}
|
||||||
|
if (bMaintainCount) m_cElements = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExplicitPurge()
|
||||||
|
{
|
||||||
|
T * pDie;
|
||||||
|
BYTE * pb;
|
||||||
|
|
||||||
|
while (m_pHead)
|
||||||
|
{
|
||||||
|
pDie = m_pHead;
|
||||||
|
m_pHead = pDie->m_pNext;
|
||||||
|
|
||||||
|
pDie->~T();
|
||||||
|
|
||||||
|
pb = reinterpret_cast<BYTE *>(pDie);
|
||||||
|
delete [] pb;
|
||||||
|
}
|
||||||
|
if (bMaintainCount) m_cElements = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
T * GetTail() const
|
||||||
|
{
|
||||||
|
if (m_pHead)
|
||||||
|
{
|
||||||
|
return m_pTail;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * GetHead() const
|
||||||
|
{
|
||||||
|
return m_pHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL IsEmpty() const
|
||||||
|
{
|
||||||
|
return m_pHead == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Remove(T * pNode)
|
||||||
|
{
|
||||||
|
if (m_pHead == pNode)
|
||||||
|
{
|
||||||
|
m_pHead = pNode->m_pNext;
|
||||||
|
if (bMaintainCount) --m_cElements;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T * pCur = m_pHead;
|
||||||
|
while (pCur)
|
||||||
|
{
|
||||||
|
T * pNext = pCur->m_pNext;
|
||||||
|
if (pNext == pNode)
|
||||||
|
{
|
||||||
|
if ((pCur->m_pNext = pNode->m_pNext) == NULL)
|
||||||
|
{
|
||||||
|
m_pTail = pCur;
|
||||||
|
}
|
||||||
|
if (bMaintainCount) --m_cElements;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
pCur = pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveAllToHeadOf(CSpBasicQueue & DestQueue)
|
||||||
|
{
|
||||||
|
if (m_pHead)
|
||||||
|
{
|
||||||
|
m_pTail->m_pNext = DestQueue.m_pHead;
|
||||||
|
if (DestQueue.m_pHead == NULL)
|
||||||
|
{
|
||||||
|
DestQueue.m_pTail = m_pTail;
|
||||||
|
}
|
||||||
|
DestQueue.m_pHead = m_pHead;
|
||||||
|
m_pHead = NULL;
|
||||||
|
if (bMaintainCount)
|
||||||
|
{
|
||||||
|
DestQueue.m_cElements += m_cElements;
|
||||||
|
m_cElements = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveAllToList(CSpBasicList<T, bPurgeWhenDeleted> & List)
|
||||||
|
{
|
||||||
|
if (m_pHead)
|
||||||
|
{
|
||||||
|
m_pTail->m_pNext = List.m_pFirst;
|
||||||
|
List.m_pFirst = m_pHead;
|
||||||
|
m_pHead = NULL;
|
||||||
|
}
|
||||||
|
if (bMaintainCount)
|
||||||
|
{
|
||||||
|
m_cElements = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MoveToList(T * pNode, CSpBasicList<T, bPurgeWhenDeleted> & List)
|
||||||
|
{
|
||||||
|
BOOL bFound = Remove(pNode);
|
||||||
|
if (bFound)
|
||||||
|
{
|
||||||
|
List.AddNode(pNode);
|
||||||
|
}
|
||||||
|
return bFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG GetCount() const
|
||||||
|
{
|
||||||
|
if (bMaintainCount)
|
||||||
|
{
|
||||||
|
return m_cElements;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ULONG c = 0;
|
||||||
|
for (T * pNode = m_pHead;
|
||||||
|
pNode;
|
||||||
|
pNode = pNode->m_pNext, c++) {}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The following functions require the class T to implement a static function:
|
||||||
|
//
|
||||||
|
// LONG Compare(const T * pElem1, const T * pElem2)
|
||||||
|
//
|
||||||
|
// which returns < 0 if pElem1 is less than pElem2, 0 if they are equal, and > 0 if
|
||||||
|
// pElem1 is greater than pElem2.
|
||||||
|
//
|
||||||
|
void InsertSorted(T * pNode)
|
||||||
|
{
|
||||||
|
if (m_pHead)
|
||||||
|
{
|
||||||
|
if (T::Compare(pNode, m_pTail) >= 0)
|
||||||
|
{
|
||||||
|
pNode->m_pNext = NULL;
|
||||||
|
m_pTail->m_pNext = pNode;
|
||||||
|
m_pTail = pNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// We don't have to worry about walking off of the end of the list here since
|
||||||
|
// we have already checked the tail.
|
||||||
|
//
|
||||||
|
T ** ppNext = &m_pHead;
|
||||||
|
while (T::Compare(pNode, *ppNext) >= 0)
|
||||||
|
{
|
||||||
|
ppNext = &((*ppNext)->m_pNext);
|
||||||
|
}
|
||||||
|
pNode->m_pNext = *ppNext;
|
||||||
|
*ppNext = pNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pNode->m_pNext = NULL;
|
||||||
|
m_pHead = m_pTail = pNode;
|
||||||
|
}
|
||||||
|
if (bMaintainCount) ++m_cElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT InsertSortedUnique(T * pNode)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (m_pHead)
|
||||||
|
{
|
||||||
|
if (T::Compare(pNode, m_pTail) > 0)
|
||||||
|
{
|
||||||
|
pNode->m_pNext = NULL;
|
||||||
|
m_pTail->m_pNext = pNode;
|
||||||
|
m_pTail = pNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// We don't have to worry about walking off of the end of the list here since
|
||||||
|
// we have already checked the tail.
|
||||||
|
//
|
||||||
|
T ** ppNext = &m_pHead;
|
||||||
|
while (T::Compare(pNode, *ppNext) > 0)
|
||||||
|
{
|
||||||
|
ppNext = &((*ppNext)->m_pNext);
|
||||||
|
}
|
||||||
|
if (T::Compare(pNode, *ppNext) != 0)
|
||||||
|
{
|
||||||
|
pNode->m_pNext = *ppNext;
|
||||||
|
*ppNext = pNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pNode;
|
||||||
|
hr = S_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pNode->m_pNext = NULL;
|
||||||
|
m_pHead = m_pTail = pNode;
|
||||||
|
}
|
||||||
|
if (bMaintainCount) ++m_cElements;
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// These functions must support the "==" operator for the TFIND type.
|
||||||
|
//
|
||||||
|
template <class TFIND>
|
||||||
|
T * Find(TFIND & FindVal) const
|
||||||
|
{
|
||||||
|
for (T * pNode = m_pHead; pNode && (!(*pNode == FindVal)); pNode = pNode->m_pNext)
|
||||||
|
{}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TFIND>
|
||||||
|
T * FindNext(const T * pCurNode, TFIND & FindVal) const
|
||||||
|
{
|
||||||
|
for (T * pNode = pCurNode->m_pNext; pNode && (!(*pNode == FindVal)); pNode = pNode->m_pNext)
|
||||||
|
{}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Searches for and removes a single list element
|
||||||
|
//
|
||||||
|
template <class TFIND>
|
||||||
|
T * FindAndRemove(TFIND & FindVal)
|
||||||
|
{
|
||||||
|
T * pNode = m_pHead;
|
||||||
|
if (pNode)
|
||||||
|
{
|
||||||
|
if (*pNode == FindVal)
|
||||||
|
{
|
||||||
|
m_pHead = pNode->m_pNext;
|
||||||
|
if (bMaintainCount) --m_cElements;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T * pPrev = pNode;
|
||||||
|
for (pNode = pNode->m_pNext;
|
||||||
|
pNode;
|
||||||
|
pPrev = pNode, pNode = pNode->m_pNext)
|
||||||
|
{
|
||||||
|
if (*pNode == FindVal)
|
||||||
|
{
|
||||||
|
pPrev->m_pNext = pNode->m_pNext;
|
||||||
|
if (pNode->m_pNext == NULL)
|
||||||
|
{
|
||||||
|
m_pTail = pPrev;
|
||||||
|
}
|
||||||
|
if (bMaintainCount) --m_cElements;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Searches for and deletes all list elements that match
|
||||||
|
//
|
||||||
|
template <class TFIND>
|
||||||
|
void FindAndDeleteAll(TFIND & FindVal)
|
||||||
|
{
|
||||||
|
T * pNode = m_pHead;
|
||||||
|
while (pNode && *pNode == FindVal)
|
||||||
|
{
|
||||||
|
m_pHead = pNode->m_pNext;
|
||||||
|
delete pNode;
|
||||||
|
if (bMaintainCount) --m_cElements;
|
||||||
|
pNode = m_pHead;
|
||||||
|
}
|
||||||
|
T * pPrev = pNode;
|
||||||
|
while (pNode)
|
||||||
|
{
|
||||||
|
T * pNext = pNode->m_pNext;
|
||||||
|
if (*pNode == FindVal)
|
||||||
|
{
|
||||||
|
pPrev->m_pNext = pNext;
|
||||||
|
delete pNode;
|
||||||
|
if (bMaintainCount) --m_cElements;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pPrev = pNode;
|
||||||
|
}
|
||||||
|
pNode = pNext;
|
||||||
|
}
|
||||||
|
m_pTail = pPrev; // Just always set it in case we removed the tail.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, BOOL bPurgeWhenDeleted = TRUE>
|
||||||
|
class CSpBasicList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T * m_pFirst;
|
||||||
|
CSpBasicList() : m_pFirst(NULL) {}
|
||||||
|
~CSpBasicList()
|
||||||
|
{
|
||||||
|
if (bPurgeWhenDeleted)
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Purge()
|
||||||
|
{
|
||||||
|
while (m_pFirst)
|
||||||
|
{
|
||||||
|
T * pNext = m_pFirst->m_pNext;
|
||||||
|
delete m_pFirst;
|
||||||
|
m_pFirst = pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExplicitPurge()
|
||||||
|
{
|
||||||
|
T * pDie;
|
||||||
|
BYTE * pb;
|
||||||
|
|
||||||
|
while (m_pFirst)
|
||||||
|
{
|
||||||
|
pDie = m_pFirst;
|
||||||
|
m_pFirst = pDie->m_pNext;
|
||||||
|
|
||||||
|
pDie->~T();
|
||||||
|
|
||||||
|
pb = reinterpret_cast<BYTE *>(pDie);
|
||||||
|
delete [] pb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT RemoveFirstOrAllocateNew(T ** ppNode)
|
||||||
|
{
|
||||||
|
if (m_pFirst)
|
||||||
|
{
|
||||||
|
*ppNode = m_pFirst;
|
||||||
|
m_pFirst = m_pFirst->m_pNext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppNode = new T;
|
||||||
|
if (*ppNode == NULL)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddNode(T * pNode)
|
||||||
|
{
|
||||||
|
pNode->m_pNext = m_pFirst;
|
||||||
|
m_pFirst = pNode;
|
||||||
|
}
|
||||||
|
T * GetFirst()
|
||||||
|
{
|
||||||
|
return m_pFirst;
|
||||||
|
}
|
||||||
|
T * RemoveFirst()
|
||||||
|
{
|
||||||
|
T * pNode = m_pFirst;
|
||||||
|
if (pNode)
|
||||||
|
{
|
||||||
|
m_pFirst = pNode->m_pNext;
|
||||||
|
}
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STACK_ALLOC(TYPE, COUNT) (TYPE *)_alloca(sizeof(TYPE) * (COUNT))
|
||||||
|
#define STACK_ALLOC_AND_ZERO(TYPE, COUNT) (TYPE *)memset(_alloca(sizeof(TYPE) * (COUNT)), 0, (sizeof(TYPE) * (COUNT)))
|
||||||
|
#define STACK_ALLOC_AND_COPY(TYPE, COUNT, SOURCE) (TYPE *)memcpy(_alloca(sizeof(TYPE) * (COUNT)), (SOURCE), (sizeof(TYPE) * (COUNT)))
|
||||||
|
|
||||||
|
inline HRESULT SpGetSubTokenFromToken(
|
||||||
|
ISpObjectToken * pToken,
|
||||||
|
const WCHAR * pszSubKeyName,
|
||||||
|
ISpObjectToken ** ppToken,
|
||||||
|
BOOL fCreateIfNotExist = FALSE)
|
||||||
|
{
|
||||||
|
SPDBG_FUNC("SpGetTokenFromDataKey");
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (SP_IS_BAD_INTERFACE_PTR(pToken) ||
|
||||||
|
SP_IS_BAD_STRING_PTR(pszSubKeyName) ||
|
||||||
|
SP_IS_BAD_WRITE_PTR(ppToken))
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, either create or open the datakey for the new token
|
||||||
|
CComPtr<ISpDataKey> cpDataKeyForNewToken;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (fCreateIfNotExist)
|
||||||
|
{
|
||||||
|
hr = pToken->CreateKey(pszSubKeyName, &cpDataKeyForNewToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = pToken->OpenKey(pszSubKeyName, &cpDataKeyForNewToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sub token's category will be the token id of it's parent token
|
||||||
|
CSpDynamicString dstrCategoryId;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pToken->GetId(&dstrCategoryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sub token's token id will be it's category id + "\\" the key name
|
||||||
|
CSpDynamicString dstrTokenId;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
dstrTokenId = dstrCategoryId;
|
||||||
|
dstrTokenId.Append2(L"\\", pszSubKeyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now create the token and initalize it
|
||||||
|
CComPtr<ISpObjectTokenInit> cpTokenInit;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpTokenInit.CoCreateInstance(CLSID_SpObjectToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpTokenInit->InitFromDataKey(dstrCategoryId, dstrTokenId, cpDataKeyForNewToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
*ppToken = cpTokenInit.Detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDBG_REPORT_ON_FAIL(hr);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
HRESULT SpCreateObjectFromSubToken(ISpObjectToken * pToken, const WCHAR * pszSubKeyName, T ** ppObject,
|
||||||
|
IUnknown * pUnkOuter = NULL, DWORD dwClsCtxt = CLSCTX_ALL)
|
||||||
|
{
|
||||||
|
SPDBG_FUNC("SpCreateObjectFromSubToken");
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
CComPtr<ISpObjectToken> cpSubToken;
|
||||||
|
hr = SpGetSubTokenFromToken(pToken, pszSubKeyName, &cpSubToken);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = SpCreateObjectFromToken(cpSubToken, ppObject, pUnkOuter, dwClsCtxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDBG_REPORT_ON_FAIL(hr);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* This must be the last line in the file */
|
25599
mp/src/utils/sapi51/Include/sapi.h
Normal file
25599
mp/src/utils/sapi51/Include/sapi.h
Normal file
File diff suppressed because it is too large
Load Diff
4557
mp/src/utils/sapi51/Include/sapiddk.h
Normal file
4557
mp/src/utils/sapi51/Include/sapiddk.h
Normal file
File diff suppressed because it is too large
Load Diff
1432
mp/src/utils/sapi51/Include/spcollec.h
Normal file
1432
mp/src/utils/sapi51/Include/spcollec.h
Normal file
File diff suppressed because it is too large
Load Diff
636
mp/src/utils/sapi51/Include/spdebug.h
Normal file
636
mp/src/utils/sapi51/Include/spdebug.h
Normal file
@ -0,0 +1,636 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* SPDebug.h *
|
||||||
|
*-----------*
|
||||||
|
* Description:
|
||||||
|
* This header file contains debug output services for SAPI5
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <TCHAR.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
|
||||||
|
#ifdef ASSERT_WITH_STACK
|
||||||
|
#include "AssertWithStack.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const TCHAR g_szSpDebugKey[] = _T("SPDebug");
|
||||||
|
const TCHAR g_szSpDebugFuncTraceReportMode[] = _T("FuncTraceMode");
|
||||||
|
const TCHAR g_szSpDebugFuncTraceReportFile[] = _T("FuncTraceFile");
|
||||||
|
const TCHAR g_szSpDebugParamInfoReportMode[] = _T("ParamInfoMode");
|
||||||
|
const TCHAR g_szSpDebugParamInfoReportFile[] = _T("ParamInfoFile");
|
||||||
|
const TCHAR g_szSpDebugDumpInfoReportMode[] = _T("DumpInfoMode");
|
||||||
|
const TCHAR g_szSpDebugDumpInfoReportFile[] = _T("DumpInfoFile");
|
||||||
|
const TCHAR g_szSpDebugAssertReportMode[] = _T("AssertMode");
|
||||||
|
const TCHAR g_szSpDebugAssertReportFile[] = _T("AssertFile");
|
||||||
|
const TCHAR g_szSpDebugHRFailReportMode[] = _T("HRFailMode");
|
||||||
|
const TCHAR g_szSpDebugHRFailReportFile[] = _T("HRFailFile");
|
||||||
|
|
||||||
|
const TCHAR g_szSpDebugAssertSettingsReReadEachTime[] = _T("AssertSettingsReReadEachTime");
|
||||||
|
const TCHAR g_szSpDebugServerOnStart[] = _T("DebugServerOnStart");
|
||||||
|
const TCHAR g_szSpDebugClientOnStart[] = _T("DebugClientOnStart");
|
||||||
|
|
||||||
|
const TCHAR g_szSpDebugLog[] = _T("c:\\spdebug.log");
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
class CSpDebug
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CSpDebug()
|
||||||
|
{
|
||||||
|
m_mutex = NULL;
|
||||||
|
m_reportModePrev = -1;
|
||||||
|
m_hfilePrev = NULL;
|
||||||
|
Read();
|
||||||
|
}
|
||||||
|
|
||||||
|
~CSpDebug()
|
||||||
|
{
|
||||||
|
if (m_mutex != NULL)
|
||||||
|
{
|
||||||
|
CloseHandle(m_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL FuncTrace(BOOL fEnter = TRUE)
|
||||||
|
{
|
||||||
|
return fEnter
|
||||||
|
? Enter(_CRT_WARN, m_FuncTraceMode, m_szFuncTraceFile)
|
||||||
|
: Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL ParamInfo(BOOL fEnter = TRUE)
|
||||||
|
{
|
||||||
|
return fEnter
|
||||||
|
? Enter(_CRT_WARN, m_ParamInfoMode, m_szParamInfoFile)
|
||||||
|
: Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL DumpInfo(BOOL fEnter = TRUE)
|
||||||
|
{
|
||||||
|
return fEnter
|
||||||
|
? Enter(_CRT_WARN, m_DumpInfoMode, m_szDumpInfoFile)
|
||||||
|
: Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Assert(BOOL fEnter = TRUE)
|
||||||
|
{
|
||||||
|
if (m_fAssertSettingsReReadEachTime)
|
||||||
|
Read();
|
||||||
|
|
||||||
|
return fEnter
|
||||||
|
? Enter(_CRT_ASSERT, m_AssertMode, m_szAssertFile)
|
||||||
|
: Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL HRFail(BOOL fEnter = TRUE)
|
||||||
|
{
|
||||||
|
return fEnter
|
||||||
|
? Enter(_CRT_WARN, m_HRFailMode, m_szHRFailFile)
|
||||||
|
: Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL DebugServerOnStart()
|
||||||
|
{
|
||||||
|
return m_fDebugServerOnStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL DebugClientOnStart()
|
||||||
|
{
|
||||||
|
return m_fDebugClientOnStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void Read()
|
||||||
|
{
|
||||||
|
HKEY hkeyDebug;
|
||||||
|
RegCreateKeyEx(
|
||||||
|
HKEY_CLASSES_ROOT,
|
||||||
|
g_szSpDebugKey,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
KEY_READ | KEY_WRITE,
|
||||||
|
NULL,
|
||||||
|
&hkeyDebug,
|
||||||
|
NULL);
|
||||||
|
if (hkeyDebug == NULL)
|
||||||
|
{
|
||||||
|
RegCreateKeyEx(
|
||||||
|
HKEY_CLASSES_ROOT,
|
||||||
|
g_szSpDebugKey,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
KEY_READ,
|
||||||
|
NULL,
|
||||||
|
&hkeyDebug,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD dw = sizeof(m_fAssertSettingsReReadEachTime);
|
||||||
|
if (RegQueryValueEx(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugAssertSettingsReReadEachTime,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
LPBYTE(&m_fAssertSettingsReReadEachTime),
|
||||||
|
&dw) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
m_fAssertSettingsReReadEachTime = FALSE;
|
||||||
|
RegSetValueEx(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugAssertSettingsReReadEachTime,
|
||||||
|
NULL,
|
||||||
|
REG_DWORD,
|
||||||
|
LPBYTE(&m_fAssertSettingsReReadEachTime),
|
||||||
|
sizeof(m_fAssertSettingsReReadEachTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadFor(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugFuncTraceReportMode,
|
||||||
|
g_szSpDebugFuncTraceReportFile,
|
||||||
|
&m_FuncTraceMode,
|
||||||
|
m_szFuncTraceFile,
|
||||||
|
0,
|
||||||
|
g_szSpDebugLog);
|
||||||
|
ReadFor(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugParamInfoReportMode,
|
||||||
|
g_szSpDebugParamInfoReportFile,
|
||||||
|
&m_ParamInfoMode,
|
||||||
|
m_szParamInfoFile,
|
||||||
|
0,
|
||||||
|
g_szSpDebugLog);
|
||||||
|
ReadFor(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugDumpInfoReportMode,
|
||||||
|
g_szSpDebugDumpInfoReportFile,
|
||||||
|
&m_DumpInfoMode,
|
||||||
|
m_szDumpInfoFile,
|
||||||
|
_CRTDBG_MODE_DEBUG,
|
||||||
|
g_szSpDebugLog);
|
||||||
|
ReadFor(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugAssertReportMode,
|
||||||
|
g_szSpDebugAssertReportFile,
|
||||||
|
&m_AssertMode,
|
||||||
|
m_szAssertFile,
|
||||||
|
_CRTDBG_MODE_WNDW,
|
||||||
|
g_szSpDebugLog);
|
||||||
|
ReadFor(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugHRFailReportMode,
|
||||||
|
g_szSpDebugHRFailReportFile,
|
||||||
|
&m_HRFailMode,
|
||||||
|
m_szHRFailFile,
|
||||||
|
_CRTDBG_MODE_DEBUG,
|
||||||
|
g_szSpDebugLog);
|
||||||
|
|
||||||
|
dw = sizeof(m_fDebugServerOnStart);
|
||||||
|
if (RegQueryValueEx(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugServerOnStart,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
LPBYTE(&m_fDebugServerOnStart),
|
||||||
|
&dw) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
m_fDebugServerOnStart = FALSE;
|
||||||
|
RegSetValueEx(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugServerOnStart,
|
||||||
|
NULL,
|
||||||
|
REG_DWORD,
|
||||||
|
LPBYTE(&m_fDebugServerOnStart),
|
||||||
|
sizeof(m_fDebugServerOnStart));
|
||||||
|
}
|
||||||
|
|
||||||
|
dw = sizeof(m_fDebugClientOnStart);
|
||||||
|
if (RegQueryValueEx(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugClientOnStart,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
LPBYTE(&m_fDebugClientOnStart),
|
||||||
|
&dw) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
m_fDebugClientOnStart = FALSE;
|
||||||
|
RegSetValueEx(
|
||||||
|
hkeyDebug,
|
||||||
|
g_szSpDebugClientOnStart,
|
||||||
|
NULL,
|
||||||
|
REG_DWORD,
|
||||||
|
LPBYTE(&m_fDebugClientOnStart),
|
||||||
|
sizeof(m_fDebugClientOnStart));
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(hkeyDebug);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadFor(
|
||||||
|
HKEY hkey,
|
||||||
|
const TCHAR * pszModeValueName,
|
||||||
|
const TCHAR * pszFileValueName,
|
||||||
|
DWORD * pdwModeValue,
|
||||||
|
TCHAR * pszFileValue,
|
||||||
|
DWORD dwDefaultModeValue,
|
||||||
|
const TCHAR * pszDefaultFileValue)
|
||||||
|
{
|
||||||
|
DWORD dw = sizeof(*pdwModeValue);
|
||||||
|
if (RegQueryValueEx(
|
||||||
|
hkey,
|
||||||
|
pszModeValueName,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
LPBYTE(pdwModeValue),
|
||||||
|
&dw) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
*pdwModeValue = dwDefaultModeValue;
|
||||||
|
RegSetValueEx(
|
||||||
|
hkey,
|
||||||
|
pszModeValueName,
|
||||||
|
NULL,
|
||||||
|
REG_DWORD,
|
||||||
|
LPBYTE(pdwModeValue),
|
||||||
|
sizeof(*pdwModeValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
dw = MAX_PATH;
|
||||||
|
if (RegQueryValueEx(
|
||||||
|
hkey,
|
||||||
|
pszFileValueName,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
LPBYTE(pszFileValue),
|
||||||
|
&dw) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
_tcscpy(pszFileValue, pszDefaultFileValue);
|
||||||
|
RegSetValueEx(
|
||||||
|
hkey,
|
||||||
|
pszFileValueName,
|
||||||
|
NULL,
|
||||||
|
REG_SZ,
|
||||||
|
LPBYTE(pszFileValue),
|
||||||
|
MAX_PATH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Enter(int reportType, DWORD &reportMode, TCHAR * pszFile)
|
||||||
|
{
|
||||||
|
if (reportMode != 0)
|
||||||
|
{
|
||||||
|
// We'll hold the mutex, until the caller also calls Leave
|
||||||
|
if (m_mutex == NULL)
|
||||||
|
{
|
||||||
|
m_mutex = CreateMutex(NULL, FALSE, _T("SpDebug"));
|
||||||
|
}
|
||||||
|
WaitForSingleObject(m_mutex, INFINITE);
|
||||||
|
|
||||||
|
m_reportType = reportType;
|
||||||
|
m_reportModePrev = _CrtSetReportMode(reportType, reportMode);
|
||||||
|
if (reportMode & _CRTDBG_MODE_FILE)
|
||||||
|
{
|
||||||
|
HANDLE hfile = CreateFile(
|
||||||
|
pszFile,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ,
|
||||||
|
NULL,
|
||||||
|
OPEN_ALWAYS,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
SetFilePointer(hfile, 0, NULL, FILE_END);
|
||||||
|
m_hfilePrev = (_HFILE)_CrtSetReportFile(reportType, (_HFILE)hfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Leave()
|
||||||
|
{
|
||||||
|
int reportMode = _CrtSetReportMode(m_reportType, m_reportModePrev);
|
||||||
|
if (reportMode & _CRTDBG_MODE_FILE)
|
||||||
|
{
|
||||||
|
CloseHandle((_HFILE)_CrtSetReportFile(m_reportType, (_HFILE)m_hfilePrev));
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseMutex(m_mutex);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
HANDLE m_mutex;
|
||||||
|
|
||||||
|
int m_reportType;
|
||||||
|
int m_reportModePrev;
|
||||||
|
_HFILE m_hfilePrev;
|
||||||
|
|
||||||
|
BOOL m_fAssertSettingsReReadEachTime;
|
||||||
|
|
||||||
|
DWORD m_FuncTraceMode;
|
||||||
|
TCHAR m_szFuncTraceFile[MAX_PATH + 1];
|
||||||
|
DWORD m_ParamInfoMode;
|
||||||
|
TCHAR m_szParamInfoFile[MAX_PATH + 1];
|
||||||
|
DWORD m_DumpInfoMode;
|
||||||
|
TCHAR m_szDumpInfoFile[MAX_PATH + 1];
|
||||||
|
DWORD m_AssertMode;
|
||||||
|
TCHAR m_szAssertFile[MAX_PATH + 1];
|
||||||
|
DWORD m_HRFailMode;
|
||||||
|
TCHAR m_szHRFailFile[MAX_PATH + 1];
|
||||||
|
|
||||||
|
BOOL m_fDebugServerOnStart;
|
||||||
|
BOOL m_fDebugClientOnStart;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline CSpDebug *PSpDebug()
|
||||||
|
{
|
||||||
|
static CSpDebug debug;
|
||||||
|
return &debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CSpFuncTrace
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CSpFuncTrace(PCHAR pFuncName)
|
||||||
|
{
|
||||||
|
m_pFuncName = pFuncName;
|
||||||
|
if (PSpDebug()->FuncTrace())
|
||||||
|
{
|
||||||
|
_RPT1( _CRT_WARN, "\nEntering Function: %s\n", m_pFuncName );
|
||||||
|
PSpDebug()->FuncTrace(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~CSpFuncTrace()
|
||||||
|
{
|
||||||
|
if (PSpDebug()->FuncTrace())
|
||||||
|
{
|
||||||
|
_RPT1( _CRT_WARN, "Leaving Function: %s\n", m_pFuncName );
|
||||||
|
PSpDebug()->FuncTrace(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PCHAR m_pFuncName;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
//=== User macros ==============================================================
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
#define SPDBG_FUNC(name) \
|
||||||
|
CSpFuncTrace functrace(name)
|
||||||
|
|
||||||
|
#if defined(ASSERT_WITH_STACK) && !defined(_WIN64)
|
||||||
|
#define SPDBG_REPORT_ON_FAIL(hr) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
HRESULT _hr = (hr); \
|
||||||
|
if (FAILED(_hr) && PSpDebug()->HRFail()) \
|
||||||
|
{ \
|
||||||
|
SYSTEMTIME sysTime; \
|
||||||
|
GetLocalTime(&sysTime); \
|
||||||
|
CHAR pszHrWithTime[100]; \
|
||||||
|
sprintf(pszHrWithTime, "%lX\n\n%d.%d.%d %02d:%02d:%02d", \
|
||||||
|
_hr, \
|
||||||
|
sysTime.wMonth,sysTime.wDay,sysTime.wYear, \
|
||||||
|
sysTime.wHour,sysTime.wMinute,sysTime.wSecond); \
|
||||||
|
PCHAR pszStack = \
|
||||||
|
(PCHAR)_alloca( \
|
||||||
|
cchMaxAssertStackLevelStringLen * \
|
||||||
|
cfrMaxAssertStackLevels + 1); \
|
||||||
|
GetStringFromStackLevels(0, 10, pszStack); \
|
||||||
|
_RPT4(_CRT_WARN, \
|
||||||
|
"%s(%d): Failed HR = %s\n\n%s\n", \
|
||||||
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
pszHrWithTime, \
|
||||||
|
pszStack); \
|
||||||
|
PSpDebug()->HRFail(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else // ASSERT_WITH_STACK & !_WIN64
|
||||||
|
#define SPDBG_REPORT_ON_FAIL(hr) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
HRESULT _hr = (hr); \
|
||||||
|
if (FAILED(_hr) && PSpDebug()->HRFail()) \
|
||||||
|
{ \
|
||||||
|
_RPT3(_CRT_WARN, "%s(%d): Failed HR = %lX\n", __FILE__, __LINE__, (_hr) );\
|
||||||
|
PSpDebug()->HRFail(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#endif // ASSERT_WITH_STACK
|
||||||
|
|
||||||
|
#define SPDBG_ASSERT(expr) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (!(expr)) \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->Assert()) \
|
||||||
|
{ \
|
||||||
|
_ASSERTE( expr ); \
|
||||||
|
PSpDebug()->Assert(FALSE); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define SPDBG_VERIFY(expr) \
|
||||||
|
SPDBG_ASSERT(expr)
|
||||||
|
|
||||||
|
#define SPDBG_PMSG0(format) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->ParamInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT0(_CRT_WARN, format); \
|
||||||
|
PSpDebug()->ParamInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPDBG_PMSG1(format, arg1) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->ParamInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT1(_CRT_WARN, format, arg1); \
|
||||||
|
PSpDebug()->ParamInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPDBG_PMSG2(format, arg1, arg2) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->ParamInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT2(_CRT_WARN, format, arg1, arg2); \
|
||||||
|
PSpDebug()->ParamInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPDBG_PMSG3(format, arg1, arg2, arg3) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->ParamInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT3(_CRT_WARN, format, arg1, arg2, arg3); \
|
||||||
|
PSpDebug()->ParamInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPDBG_PMSG4(format, arg1, arg2, arg3, arg4) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->ParamInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT4(_CRT_WARN, format, arg1, arg2, arg3, arg4); \
|
||||||
|
PSpDebug()->ParamInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SPDBG_DMSG0(format) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->DumpInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT0(_CRT_WARN, format); \
|
||||||
|
PSpDebug()->DumpInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPDBG_DMSG1(format, arg1) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->DumpInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT1(_CRT_WARN, format, arg1); \
|
||||||
|
PSpDebug()->DumpInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPDBG_DMSG2(format, arg1, arg2) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->DumpInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT2(_CRT_WARN, format, arg1, arg2); \
|
||||||
|
PSpDebug()->DumpInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPDBG_DMSG3(format, arg1, arg2, arg3) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->DumpInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT3(_CRT_WARN, format, arg1, arg2, arg3); \
|
||||||
|
PSpDebug()->DumpInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPDBG_DMSG4(format, arg1, arg2, arg3, arg4) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->DumpInfo()) \
|
||||||
|
{ \
|
||||||
|
_RPT4(_CRT_WARN, format, arg1, arg2, arg3, arg4); \
|
||||||
|
PSpDebug()->DumpInfo(FALSE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SPDBG_RETURN(hr) \
|
||||||
|
{ \
|
||||||
|
HRESULT __hr = (hr); \
|
||||||
|
if (FAILED(__hr)) \
|
||||||
|
{ \
|
||||||
|
SPDBG_REPORT_ON_FAIL(__hr); \
|
||||||
|
} \
|
||||||
|
return __hr; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPDBG_DEBUG_SERVER_ON_START() \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->DebugServerOnStart()) \
|
||||||
|
{ \
|
||||||
|
if (MessageBox( \
|
||||||
|
GetDesktopWindow(), \
|
||||||
|
_T("Attach Debugger to the SAPI Server process?"), \
|
||||||
|
_T("SAPI"), \
|
||||||
|
MB_YESNO) == IDYES) \
|
||||||
|
{ \
|
||||||
|
USES_CONVERSION; \
|
||||||
|
TCHAR szCommand[MAX_PATH + 1]; \
|
||||||
|
wsprintf( \
|
||||||
|
szCommand, \
|
||||||
|
_T("msdev -p %d"), \
|
||||||
|
GetCurrentProcessId()); \
|
||||||
|
system(T2A(szCommand)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPDBG_DEBUG_CLIENT_ON_START() \
|
||||||
|
{ \
|
||||||
|
if (PSpDebug()->DebugClientOnStart()) \
|
||||||
|
{ \
|
||||||
|
TCHAR szModule[MAX_PATH + 1]; \
|
||||||
|
szModule[0] = '\0'; \
|
||||||
|
TCHAR * pszSapiServer = \
|
||||||
|
_T("sapisvr.exe"); \
|
||||||
|
GetModuleFileName( \
|
||||||
|
NULL, \
|
||||||
|
szModule, \
|
||||||
|
MAX_PATH); \
|
||||||
|
if ((_tcslen(szModule) <= \
|
||||||
|
_tcslen(pszSapiServer) || \
|
||||||
|
_tcsicmp( \
|
||||||
|
szModule + \
|
||||||
|
_tcslen(szModule) - \
|
||||||
|
_tcslen(pszSapiServer), \
|
||||||
|
pszSapiServer) != 0) && \
|
||||||
|
MessageBox( \
|
||||||
|
GetDesktopWindow(), \
|
||||||
|
_T("Attach Debugger to the SAPI Client process?"), \
|
||||||
|
_T("SAPI"), \
|
||||||
|
MB_YESNO) == IDYES) \
|
||||||
|
{ \
|
||||||
|
USES_CONVERSION; \
|
||||||
|
TCHAR szCommand[MAX_PATH + 1]; \
|
||||||
|
wsprintf( \
|
||||||
|
szCommand, \
|
||||||
|
_T("msdev -p %d"), \
|
||||||
|
GetCurrentProcessId()); \
|
||||||
|
system(T2A(szCommand)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // _DEBUG
|
||||||
|
|
||||||
|
#define SPDBG_FUNC(name)
|
||||||
|
#define SPDBG_REPORT_ON_FAIL(hr)
|
||||||
|
#define SPDBG_ASSERT(expr)
|
||||||
|
#define SPDBG_VERIFY(expr) (expr)
|
||||||
|
#define SPDBG_PMSG0(format)
|
||||||
|
#define SPDBG_PMSG1(format, arg1)
|
||||||
|
#define SPDBG_PMSG2(format, arg1, arg2)
|
||||||
|
#define SPDBG_PMSG3(format, arg1, arg2, arg3)
|
||||||
|
#define SPDBG_PMSG4(format, arg1, arg2, arg3, arg4)
|
||||||
|
#define SPDBG_DMSG0(format)
|
||||||
|
#define SPDBG_DMSG1(format, arg1)
|
||||||
|
#define SPDBG_DMSG2(format, arg1, arg2)
|
||||||
|
#define SPDBG_DMSG3(format, arg1, arg2, arg3)
|
||||||
|
#define SPDBG_DMSG4(format, arg1, arg2, arg3, arg4)
|
||||||
|
#define SPDBG_RETURN(hr) return (hr)
|
||||||
|
#define SPDBG_DEBUG_SERVER_ON_START()
|
||||||
|
#define SPDBG_DEBUG_CLIENT_ON_START()
|
||||||
|
|
||||||
|
#endif // _DEBUG
|
559
mp/src/utils/sapi51/Include/sperror.h
Normal file
559
mp/src/utils/sapi51/Include/sperror.h
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* SPError.h *
|
||||||
|
*-----------*
|
||||||
|
* Description:
|
||||||
|
* This header file contains the custom error codes specific to SAPI5
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*******************************************************************************/
|
||||||
|
#ifndef SPError_h
|
||||||
|
#define SPError_h
|
||||||
|
|
||||||
|
#ifndef _WINERROR_
|
||||||
|
#include <winerror.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FACILITY_SAPI FACILITY_ITF
|
||||||
|
#define SAPI_ERROR_BASE 0x5000
|
||||||
|
|
||||||
|
#define MAKE_SAPI_HRESULT(sev, err) MAKE_HRESULT(sev, FACILITY_SAPI, err)
|
||||||
|
#define MAKE_SAPI_ERROR(err) MAKE_SAPI_HRESULT(SEVERITY_ERROR, err + SAPI_ERROR_BASE)
|
||||||
|
#define MAKE_SAPI_SCODE(scode) MAKE_SAPI_HRESULT(SEVERITY_SUCCESS, scode + SAPI_ERROR_BASE)
|
||||||
|
|
||||||
|
/*** SPERR_UNINITIALIZED 0x80045001 -2147201023
|
||||||
|
* The object has not been properly initialized.
|
||||||
|
*/
|
||||||
|
#define SPERR_UNINITIALIZED MAKE_SAPI_ERROR(0x001)
|
||||||
|
|
||||||
|
/*** SPERR_ALREADY_INITIALIZED 0x80045002 -2147201022
|
||||||
|
* The object has already been initialized.
|
||||||
|
*/
|
||||||
|
#define SPERR_ALREADY_INITIALIZED MAKE_SAPI_ERROR(0x002)
|
||||||
|
|
||||||
|
/*** SPERR_UNSUPPORTED_FORMAT 0x80045003 -2147201021
|
||||||
|
* The caller has specified an unsupported format.
|
||||||
|
*/
|
||||||
|
#define SPERR_UNSUPPORTED_FORMAT MAKE_SAPI_ERROR(0x003)
|
||||||
|
|
||||||
|
/*** SPERR_INVALID_FLAGS 0x80045004 -2147201020
|
||||||
|
* The caller has specified invalid flags for this operation.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_FLAGS MAKE_SAPI_ERROR(0x004)
|
||||||
|
|
||||||
|
/*** SP_END_OF_STREAM 0x00045005 282629
|
||||||
|
* The operation has reached the end of stream.
|
||||||
|
*/
|
||||||
|
#define SP_END_OF_STREAM MAKE_SAPI_SCODE(0x005)
|
||||||
|
|
||||||
|
/*** SPERR_DEVICE_BUSY 0x80045006 -2147201018
|
||||||
|
* The wave device is busy.
|
||||||
|
*/
|
||||||
|
#define SPERR_DEVICE_BUSY MAKE_SAPI_ERROR(0x006)
|
||||||
|
|
||||||
|
/*** SPERR_DEVICE_NOT_SUPPORTED 0x80045007 -2147201017
|
||||||
|
* The wave device is not supported.
|
||||||
|
*/
|
||||||
|
#define SPERR_DEVICE_NOT_SUPPORTED MAKE_SAPI_ERROR(0x007)
|
||||||
|
|
||||||
|
/*** SPERR_DEVICE_NOT_ENABLED 0x80045008 -2147201016
|
||||||
|
* The wave device is not enabled.
|
||||||
|
*/
|
||||||
|
#define SPERR_DEVICE_NOT_ENABLED MAKE_SAPI_ERROR(0x008)
|
||||||
|
|
||||||
|
/*** SPERR_NO_DRIVER 0x80045009 -2147201015
|
||||||
|
* There is no wave driver installed.
|
||||||
|
*/
|
||||||
|
#define SPERR_NO_DRIVER MAKE_SAPI_ERROR(0x009)
|
||||||
|
|
||||||
|
/*** SPERR_FILEMUSTBEUNICODE 0x8004500a -2147201014
|
||||||
|
* The file must be Unicode.
|
||||||
|
*/
|
||||||
|
#define SPERR_FILE_MUST_BE_UNICODE MAKE_SAPI_ERROR(0x00a)
|
||||||
|
|
||||||
|
/*** SP_INSUFFICIENTDATA 0x0004500b 282635
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define SP_INSUFFICIENT_DATA MAKE_SAPI_SCODE(0x00b)
|
||||||
|
|
||||||
|
/*** SPERR_INVALID_PHRASE_ID 0x8004500c -2147201012
|
||||||
|
* The phrase ID specified does not exist or is out of range.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_PHRASE_ID MAKE_SAPI_ERROR(0x00c)
|
||||||
|
|
||||||
|
/*** SPERR_BUFFER_TOO_SMALL 0x8004500d -2147201011
|
||||||
|
* The caller provided a buffer too small to return a result.
|
||||||
|
*/
|
||||||
|
#define SPERR_BUFFER_TOO_SMALL MAKE_SAPI_ERROR(0x00d)
|
||||||
|
|
||||||
|
/*** SPERR_FORMAT_NOT_SPECIFIED 0x8004500e -2147201010
|
||||||
|
* Caller did not specify a format prior to opening a stream.
|
||||||
|
*/
|
||||||
|
#define SPERR_FORMAT_NOT_SPECIFIED MAKE_SAPI_ERROR(0x00e)
|
||||||
|
|
||||||
|
/*** SPERR_AUDIO_STOPPED 0x8004500f -2147201009
|
||||||
|
* This method is deprecated. Use SP_AUDIO_STOPPED instead.
|
||||||
|
*/
|
||||||
|
#define SPERR_AUDIO_STOPPED MAKE_SAPI_ERROR(0x00f)
|
||||||
|
|
||||||
|
/*** SP_AUDIO_PAUSED 0x00045010 282640
|
||||||
|
* This will be returned only on input (read) streams when the stream is paused. Reads on
|
||||||
|
* paused streams will not block, and this return code indicates that all of the data has been
|
||||||
|
* removed from the stream.
|
||||||
|
*/
|
||||||
|
#define SP_AUDIO_PAUSED MAKE_SAPI_SCODE(0x010)
|
||||||
|
|
||||||
|
/*** SPERR_RULE_NOT_FOUND 0x80045011 -2147201007
|
||||||
|
* Invalid rule name passed to ActivateGrammar.
|
||||||
|
*/
|
||||||
|
#define SPERR_RULE_NOT_FOUND MAKE_SAPI_ERROR(0x011)
|
||||||
|
|
||||||
|
/*** SPERR_TTS_ENGINE_EXCEPTION 0x80045012 -2147201006
|
||||||
|
* An exception was raised during a call to the current TTS driver.
|
||||||
|
*/
|
||||||
|
#define SPERR_TTS_ENGINE_EXCEPTION MAKE_SAPI_ERROR(0x012)
|
||||||
|
|
||||||
|
/*** SPERR_TTS_NLP_EXCEPTION 0x80045013 -2147201005
|
||||||
|
* An exception was raised during a call to an application sentence filter.
|
||||||
|
*/
|
||||||
|
#define SPERR_TTS_NLP_EXCEPTION MAKE_SAPI_ERROR(0x013)
|
||||||
|
|
||||||
|
/*** SPERR_ENGINE_BUSY 0x80045014 -2147201004
|
||||||
|
* In speech recognition, the current method can not be performed while
|
||||||
|
* a grammar rule is active.
|
||||||
|
*/
|
||||||
|
#define SPERR_ENGINE_BUSY MAKE_SAPI_ERROR(0x014)
|
||||||
|
|
||||||
|
/*** SP_AUDIO_CONVERSION_ENABLED 0x00045015 282645
|
||||||
|
* The operation was successful, but only with automatic stream format conversion.
|
||||||
|
*/
|
||||||
|
#define SP_AUDIO_CONVERSION_ENABLED MAKE_SAPI_SCODE(0x015)
|
||||||
|
|
||||||
|
/*** SP_NO_HYPOTHESIS_AVAILABLE 0x00045016 282646
|
||||||
|
* There is currently no hypothesis recognition available.
|
||||||
|
*/
|
||||||
|
#define SP_NO_HYPOTHESIS_AVAILABLE MAKE_SAPI_SCODE(0x016)
|
||||||
|
|
||||||
|
/*** SPERR_CANT_CREATE 0x80045017 -2147201001
|
||||||
|
* Can not create a new object instance for the specified object category.
|
||||||
|
*/
|
||||||
|
#define SPERR_CANT_CREATE MAKE_SAPI_ERROR(0x017)
|
||||||
|
|
||||||
|
/*** SP_ALREADY_IN_LEX 0x00045018 282648
|
||||||
|
* The word, pronunciation, or POS pair being added is already in lexicon.
|
||||||
|
*/
|
||||||
|
#define SP_ALREADY_IN_LEX MAKE_SAPI_SCODE(0x018)
|
||||||
|
|
||||||
|
/*** SPERR_NOT_IN_LEX 0x80045019 -2147200999
|
||||||
|
* The word does not exist in the lexicon.
|
||||||
|
*/
|
||||||
|
#define SPERR_NOT_IN_LEX MAKE_SAPI_ERROR(0x019)
|
||||||
|
|
||||||
|
/*** SP_LEX_NOTHING_TO_SYNC 0x0004501a 282650
|
||||||
|
* The client is currently synced with the lexicon.
|
||||||
|
*/
|
||||||
|
#define SP_LEX_NOTHING_TO_SYNC MAKE_SAPI_SCODE(0x01a)
|
||||||
|
|
||||||
|
/*** SPERR_LEX_VERY_OUT_OF_SYNC 0x8004501b -2147200997
|
||||||
|
* The client is excessively out of sync with the lexicon. Mismatches may not be incrementally sync'd.
|
||||||
|
*/
|
||||||
|
#define SPERR_LEX_VERY_OUT_OF_SYNC MAKE_SAPI_ERROR(0x01b)
|
||||||
|
|
||||||
|
/*** SPERR_UNDEFINED_FORWARD_RULE_REF 0x8004501c -2147200996
|
||||||
|
* A rule reference in a grammar was made to a named rule that was never defined.
|
||||||
|
*/
|
||||||
|
#define SPERR_UNDEFINED_FORWARD_RULE_REF MAKE_SAPI_ERROR(0x01c)
|
||||||
|
|
||||||
|
/*** SPERR_EMPTY_RULE 0x8004501d -2147200995
|
||||||
|
* A non-dynamic grammar rule that has no body.
|
||||||
|
*/
|
||||||
|
#define SPERR_EMPTY_RULE MAKE_SAPI_ERROR(0x01d)
|
||||||
|
|
||||||
|
/*** SPERR_GRAMMAR_COMPILER_INTERNAL_ERROR 0x8004501e -2147200994
|
||||||
|
* The grammar compiler failed due to an internal state error.
|
||||||
|
*/
|
||||||
|
#define SPERR_GRAMMAR_COMPILER_INTERNAL_ERROR MAKE_SAPI_ERROR(0x01e)
|
||||||
|
|
||||||
|
|
||||||
|
/*** SPERR_RULE_NOT_DYNAMIC 0x8004501f -2147200993
|
||||||
|
* An attempt was made to modify a non-dynamic rule.
|
||||||
|
*/
|
||||||
|
#define SPERR_RULE_NOT_DYNAMIC MAKE_SAPI_ERROR(0x01f)
|
||||||
|
|
||||||
|
/*** SPERR_DUPLICATE_RULE_NAME 0x80045020 -2147200992
|
||||||
|
* A rule name was duplicated.
|
||||||
|
*/
|
||||||
|
#define SPERR_DUPLICATE_RULE_NAME MAKE_SAPI_ERROR(0x020)
|
||||||
|
|
||||||
|
/*** SPERR_DUPLICATE_RESOURCE_NAME 0x80045021 -2147200991
|
||||||
|
* A resource name was duplicated for a given rule.
|
||||||
|
*/
|
||||||
|
#define SPERR_DUPLICATE_RESOURCE_NAME MAKE_SAPI_ERROR(0x021)
|
||||||
|
|
||||||
|
|
||||||
|
/*** SPERR_TOO_MANY_GRAMMARS 0x80045022 -2147200990
|
||||||
|
* Too many grammars have been loaded.
|
||||||
|
*/
|
||||||
|
#define SPERR_TOO_MANY_GRAMMARS MAKE_SAPI_ERROR(0x022)
|
||||||
|
|
||||||
|
/*** SPERR_CIRCULAR_REFERENCE 0x80045023 -2147200989
|
||||||
|
* Circular reference in import rules of grammars.
|
||||||
|
*/
|
||||||
|
#define SPERR_CIRCULAR_REFERENCE MAKE_SAPI_ERROR(0x023)
|
||||||
|
|
||||||
|
/*** SPERR_INVALID_IMPORT 0x80045024 -2147200988
|
||||||
|
* A rule reference to an imported grammar that could not be resolved.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_IMPORT MAKE_SAPI_ERROR(0x024)
|
||||||
|
|
||||||
|
/*** SPERR_INVALID_WAV_FILE 0x80045025 -2147200987
|
||||||
|
* The format of the WAV file is not supported.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_WAV_FILE MAKE_SAPI_ERROR(0x025)
|
||||||
|
|
||||||
|
/*** SP_REQUEST_PENDING 0x00045026 282662
|
||||||
|
* This success code indicates that an SR method called with the SPRIF_ASYNC flag is
|
||||||
|
* being processed. When it has finished processing, an SPFEI_ASYNC_COMPLETED event will be generated.
|
||||||
|
*/
|
||||||
|
#define SP_REQUEST_PENDING MAKE_SAPI_SCODE(0x026)
|
||||||
|
|
||||||
|
/*** SPERR_ALL_WORDS_OPTIONAL 0x80045027 -2147200985
|
||||||
|
* A grammar rule was defined with a null path through the rule. That is, it is possible
|
||||||
|
* to satisfy the rule conditions with no words.
|
||||||
|
*/
|
||||||
|
#define SPERR_ALL_WORDS_OPTIONAL MAKE_SAPI_ERROR(0x027)
|
||||||
|
|
||||||
|
/*** SPERR_INSTANCE_CHANGE_INVALID 0x80045028 -2147200984
|
||||||
|
* It is not possible to change the current engine or input. This occurs in the
|
||||||
|
* following cases:
|
||||||
|
*
|
||||||
|
* 1) SelectEngine called while a recognition context exists, or
|
||||||
|
* 2) SetInput called in the shared instance case.
|
||||||
|
*/
|
||||||
|
#define SPERR_INSTANCE_CHANGE_INVALID MAKE_SAPI_ERROR(0x028)
|
||||||
|
|
||||||
|
/*** SPERR_RULE_NAME_ID_CONFLICT 0x80045029 -2147200983
|
||||||
|
* A rule exists with matching IDs (names) but different names (IDs).
|
||||||
|
*/
|
||||||
|
#define SPERR_RULE_NAME_ID_CONFLICT MAKE_SAPI_ERROR(0x029)
|
||||||
|
|
||||||
|
/*** SPERR_NO_RULES 0x8004502a -2147200982
|
||||||
|
* A grammar contains no top-level, dynamic, or exported rules. There is no possible
|
||||||
|
* way to activate or otherwise use any rule in this grammar.
|
||||||
|
*/
|
||||||
|
#define SPERR_NO_RULES MAKE_SAPI_ERROR(0x02a)
|
||||||
|
|
||||||
|
/*** SPERR_CIRCULAR_RULE_REF 0x8004502b -2147200981
|
||||||
|
* Rule 'A' refers to a second rule 'B' which, in turn, refers to rule 'A'.
|
||||||
|
*/
|
||||||
|
#define SPERR_CIRCULAR_RULE_REF MAKE_SAPI_ERROR(0x02b)
|
||||||
|
|
||||||
|
/*** SP_NO_PARSE_FOUND 0x0004502c 282668
|
||||||
|
* Parse path cannot be parsed given the currently active rules.
|
||||||
|
*/
|
||||||
|
#define SP_NO_PARSE_FOUND MAKE_SAPI_SCODE(0x02c)
|
||||||
|
|
||||||
|
/*** SPERR_NO_PARSE_FOUND 0x8004502d -2147200979
|
||||||
|
* Parse path cannot be parsed given the currently active rules.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_HANDLE MAKE_SAPI_ERROR(0x02d)
|
||||||
|
|
||||||
|
/*** SPERR_REMOTE_CALL_TIMED_OUT 0x8004502e -2147200978
|
||||||
|
* A marshaled remote call failed to respond.
|
||||||
|
*/
|
||||||
|
#define SPERR_REMOTE_CALL_TIMED_OUT MAKE_SAPI_ERROR(0x02e)
|
||||||
|
|
||||||
|
/*** SPERR_AUDIO_BUFFER_OVERFLOW 0x8004502f -2147200977
|
||||||
|
* This will only be returned on input (read) streams when the stream is paused because
|
||||||
|
* the SR driver has not retrieved data recently.
|
||||||
|
*/
|
||||||
|
#define SPERR_AUDIO_BUFFER_OVERFLOW MAKE_SAPI_ERROR(0x02f)
|
||||||
|
|
||||||
|
|
||||||
|
/*** SPERR_NO_AUDIO_DATA 0x80045030 -2147200976
|
||||||
|
* The result does not contain any audio, nor does the portion of the element chain of the result
|
||||||
|
* contain any audio.
|
||||||
|
*/
|
||||||
|
#define SPERR_NO_AUDIO_DATA MAKE_SAPI_ERROR(0x030)
|
||||||
|
|
||||||
|
/*** SPERR_DEAD_ALTERNATE 0x80045031 -2147200975
|
||||||
|
* This alternate is no longer a valid alternate to the result it was obtained from.
|
||||||
|
* Returned from ISpPhraseAlt methods.
|
||||||
|
*/
|
||||||
|
#define SPERR_DEAD_ALTERNATE MAKE_SAPI_ERROR(0x031)
|
||||||
|
|
||||||
|
/*** SPERR_HIGH_LOW_CONFIDENCE 0x80045032 -2147200974
|
||||||
|
* The result does not contain any audio, nor does the portion of the element chain of the result
|
||||||
|
* contain any audio. Returned from ISpResult::GetAudio and ISpResult::SpeakAudio.
|
||||||
|
*/
|
||||||
|
#define SPERR_HIGH_LOW_CONFIDENCE MAKE_SAPI_ERROR(0x032)
|
||||||
|
|
||||||
|
/*** SPERR_INVALID_FORMAT_STRING 0x80045033 -2147200973
|
||||||
|
* The XML format string for this RULEREF is invalid, e.g. not a GUID or REFCLSID.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_FORMAT_STRING MAKE_SAPI_ERROR(0x033)
|
||||||
|
|
||||||
|
/*** SP_UNSUPPORTED_ON_STREAM_INPUT 0x00045034 282676
|
||||||
|
* The operation is not supported for stream input.
|
||||||
|
*/
|
||||||
|
#define SP_UNSUPPORTED_ON_STREAM_INPUT MAKE_SAPI_SCODE(0x034)
|
||||||
|
|
||||||
|
/*** SPERR_APPLEX_READ_ONLY 0x80045035 -2147200971
|
||||||
|
* The operation is invalid for all but newly created application lexicons.
|
||||||
|
*/
|
||||||
|
#define SPERR_APPLEX_READ_ONLY MAKE_SAPI_ERROR(0x035)
|
||||||
|
|
||||||
|
/*** SPERR_NO_TERMINATING_RULE_PATH 0x80045036 -2147200970
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SPERR_NO_TERMINATING_RULE_PATH MAKE_SAPI_ERROR(0x036)
|
||||||
|
|
||||||
|
/*** SP_WORD_EXISTS_WITHOUT_PRONUNCIATION 0x00045037 282679
|
||||||
|
* The word exists but without pronunciation.
|
||||||
|
*/
|
||||||
|
#define SP_WORD_EXISTS_WITHOUT_PRONUNCIATION MAKE_SAPI_SCODE(0x037)
|
||||||
|
|
||||||
|
/*** SPERR_STREAM_CLOSED 0x80045038 -2147200968
|
||||||
|
* An operation was attempted on a stream object that has been closed.
|
||||||
|
*/
|
||||||
|
#define SPERR_STREAM_CLOSED MAKE_SAPI_ERROR(0x038)
|
||||||
|
|
||||||
|
// --- The following error codes are taken directly from WIN32 ---
|
||||||
|
|
||||||
|
/*** SPERR_NO_MORE_ITEMS 0x80045039 -2147200967
|
||||||
|
* When enumerating items, the requested index is greater than the count of items.
|
||||||
|
*/
|
||||||
|
#define SPERR_NO_MORE_ITEMS MAKE_SAPI_ERROR(0x039)
|
||||||
|
|
||||||
|
/*** SPERR_NOT_FOUND 0x8004503a -2147200966
|
||||||
|
* The requested data item (data key, value, etc.) was not found.
|
||||||
|
*/
|
||||||
|
#define SPERR_NOT_FOUND MAKE_SAPI_ERROR(0x03a)
|
||||||
|
|
||||||
|
/*** SPERR_INVALID_AUDIO_STATE 0x8004503b -2147200965
|
||||||
|
* Audio state passed to SetState() is invalid.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_AUDIO_STATE MAKE_SAPI_ERROR(0x03b)
|
||||||
|
|
||||||
|
/*** SPERR_GENERIC_MMSYS_ERROR 0x8004503c -2147200964
|
||||||
|
* A generic MMSYS error not caught by _MMRESULT_TO_HRESULT.
|
||||||
|
*/
|
||||||
|
#define SPERR_GENERIC_MMSYS_ERROR MAKE_SAPI_ERROR(0x03c)
|
||||||
|
|
||||||
|
/*** SPERR_MARSHALER_EXCEPTION 0x8004503d -2147200963
|
||||||
|
* An exception was raised during a call to the marshaling code.
|
||||||
|
*/
|
||||||
|
#define SPERR_MARSHALER_EXCEPTION MAKE_SAPI_ERROR(0x03d)
|
||||||
|
|
||||||
|
/*** SPERR_NOT_DYNAMIC_GRAMMAR 0x8004503e -2147200962
|
||||||
|
* Attempt was made to manipulate a non-dynamic grammar.
|
||||||
|
*/
|
||||||
|
#define SPERR_NOT_DYNAMIC_GRAMMAR MAKE_SAPI_ERROR(0x03e)
|
||||||
|
|
||||||
|
/*** SPERR_AMBIGUOUS_PROPERTY 0x8004503f -2147200961
|
||||||
|
* Cannot add ambiguous property.
|
||||||
|
*/
|
||||||
|
#define SPERR_AMBIGUOUS_PROPERTY MAKE_SAPI_ERROR(0x03f)
|
||||||
|
|
||||||
|
/*** SPERR_INVALID_REGISTRY_KEY 0x80045040 -2147200960
|
||||||
|
* The key specified is invalid.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_REGISTRY_KEY MAKE_SAPI_ERROR(0x040)
|
||||||
|
|
||||||
|
/*** SPERR_INVALID_TOKEN_ID 0x80045041 -2147200959
|
||||||
|
* The token specified is invalid.
|
||||||
|
*/
|
||||||
|
#define SPERR_INVALID_TOKEN_ID MAKE_SAPI_ERROR(0x041)
|
||||||
|
|
||||||
|
/*** SPERR_XML_BAD_SYNTAX 0x80045042 -2147200958
|
||||||
|
* The xml parser failed due to bad syntax.
|
||||||
|
*/
|
||||||
|
#define SPERR_XML_BAD_SYNTAX MAKE_SAPI_ERROR(0x042)
|
||||||
|
|
||||||
|
/*** SPERR_XML_RESOURCE_NOT_FOUND 0x80045043 -2147200957
|
||||||
|
* The xml parser failed to load a required resource (e.g., voice, phoneconverter, etc.).
|
||||||
|
*/
|
||||||
|
#define SPERR_XML_RESOURCE_NOT_FOUND MAKE_SAPI_ERROR(0x043)
|
||||||
|
|
||||||
|
/*** SPERR_TOKEN_IN_USE 0x80045044 -2147200956
|
||||||
|
* Attempted to remove registry data from a token that is already in use elsewhere.
|
||||||
|
*/
|
||||||
|
#define SPERR_TOKEN_IN_USE MAKE_SAPI_ERROR(0x044)
|
||||||
|
|
||||||
|
/*** SPERR_TOKEN_DELETED 0x80045045 -2147200955
|
||||||
|
* Attempted to perform an action on an object token that has had associated registry key deleted.
|
||||||
|
*/
|
||||||
|
#define SPERR_TOKEN_DELETED MAKE_SAPI_ERROR(0x045)
|
||||||
|
|
||||||
|
/*** SPERR_MULTI_LINGUAL_NOT_SUPPORTED 0x80045046 -2147200954
|
||||||
|
* The selected voice was registered as multi-lingual. SAPI does not support multi-lingual registration.
|
||||||
|
*/
|
||||||
|
#define SPERR_MULTI_LINGUAL_NOT_SUPPORTED MAKE_SAPI_ERROR(0x046)
|
||||||
|
|
||||||
|
/*** SPERR_EXPORT_DYNAMIC_RULE 0x80045047 -2147200953
|
||||||
|
* Exported rules cannot refer directly or indirectly to a dynamic rule.
|
||||||
|
*/
|
||||||
|
#define SPERR_EXPORT_DYNAMIC_RULE MAKE_SAPI_ERROR(0x047)
|
||||||
|
|
||||||
|
/*** SPERR_STGF_ERROR 0x80045048 -2147200952
|
||||||
|
* Error parsing the SAPI Text Grammar Format (XML grammar).
|
||||||
|
*/
|
||||||
|
#define SPERR_STGF_ERROR MAKE_SAPI_ERROR(0x048)
|
||||||
|
|
||||||
|
/*** SPERR_WORDFORMAT_ERROR 0x80045049 -2147200951
|
||||||
|
* Incorrect word format, probably due to incorrect pronunciation string.
|
||||||
|
*/
|
||||||
|
#define SPERR_WORDFORMAT_ERROR MAKE_SAPI_ERROR(0x049)
|
||||||
|
|
||||||
|
/*** SPERR_STREAM_NOT_ACTIVE 0x8004504a -2147200950
|
||||||
|
* Methods associated with active audio stream cannot be called unless stream is active.
|
||||||
|
*/
|
||||||
|
#define SPERR_STREAM_NOT_ACTIVE MAKE_SAPI_ERROR(0x04a)
|
||||||
|
|
||||||
|
/*** SPERR_ENGINE_RESPONSE_INVALID 0x8004504b -2147200949
|
||||||
|
* Arguments or data supplied by the engine are in an invalid format or are inconsistent.
|
||||||
|
*/
|
||||||
|
#define SPERR_ENGINE_RESPONSE_INVALID MAKE_SAPI_ERROR(0x04b)
|
||||||
|
|
||||||
|
/*** SPERR_SR_ENGINE_EXCEPTION 0x8004504c -2147200948
|
||||||
|
* An exception was raised during a call to the current SR engine.
|
||||||
|
*/
|
||||||
|
#define SPERR_SR_ENGINE_EXCEPTION MAKE_SAPI_ERROR(0x04c)
|
||||||
|
|
||||||
|
/*** SPERR_STREAM_POS_INVALID 0x8004504d -2147200947
|
||||||
|
* Stream position information supplied from engine is inconsistent.
|
||||||
|
*/
|
||||||
|
#define SPERR_STREAM_POS_INVALID MAKE_SAPI_ERROR(0x04d)
|
||||||
|
|
||||||
|
/*** SP_RECOGNIZER_INACTIVE 0x0004504e 282702
|
||||||
|
* Operation could not be completed because the recognizer is inactive. It is inactive either
|
||||||
|
* because the recognition state is currently inactive or because no rules are active .
|
||||||
|
*/
|
||||||
|
#define SP_RECOGNIZER_INACTIVE MAKE_SAPI_SCODE(0x04e)
|
||||||
|
|
||||||
|
/*** SPERR_REMOTE_CALL_ON_WRONG_THREAD 0x8004504f -2147200945
|
||||||
|
* When making a remote call to the server, the call was made on the wrong thread.
|
||||||
|
*/
|
||||||
|
#define SPERR_REMOTE_CALL_ON_WRONG_THREAD MAKE_SAPI_ERROR(0x04f)
|
||||||
|
|
||||||
|
/*** SPERR_REMOTE_PROCESS_TERMINATED 0x80045050 -2147200944
|
||||||
|
* The remote process terminated unexpectedly.
|
||||||
|
*/
|
||||||
|
#define SPERR_REMOTE_PROCESS_TERMINATED MAKE_SAPI_ERROR(0x050)
|
||||||
|
|
||||||
|
/*** SPERR_REMOTE_PROCESS_ALREADY_RUNNING 0x80045051 -2147200943
|
||||||
|
* The remote process is already running; it cannot be started a second time.
|
||||||
|
*/
|
||||||
|
#define SPERR_REMOTE_PROCESS_ALREADY_RUNNING MAKE_SAPI_ERROR(0x051)
|
||||||
|
|
||||||
|
/*** SPERR_LANGID_MISMATCH 0x80045052 -2147200942
|
||||||
|
* An attempt to load a CFG grammar with a LANGID different than other loaded grammars.
|
||||||
|
*/
|
||||||
|
#define SPERR_LANGID_MISMATCH MAKE_SAPI_ERROR(0x052)
|
||||||
|
|
||||||
|
/*** SP_PARTIAL_PARSE_FOUND 0x00045053 282707
|
||||||
|
* A grammar-ending parse has been found that does not use all available words.
|
||||||
|
*/
|
||||||
|
#define SP_PARTIAL_PARSE_FOUND MAKE_SAPI_SCODE(0x053)
|
||||||
|
|
||||||
|
/*** SPERR_NOT_TOPLEVEL_RULE 0x80045054 -2147200940
|
||||||
|
* An attempt to deactivate or activate a non-toplevel rule.
|
||||||
|
*/
|
||||||
|
#define SPERR_NOT_TOPLEVEL_RULE MAKE_SAPI_ERROR(0x054)
|
||||||
|
|
||||||
|
/*** SP_NO_RULE_ACTIVE 0x00045055 282709
|
||||||
|
* An attempt to parse when no rule was active.
|
||||||
|
*/
|
||||||
|
#define SP_NO_RULE_ACTIVE MAKE_SAPI_SCODE(0x055)
|
||||||
|
|
||||||
|
/*** SPERR_LEX_REQUIRES_COOKIE 0x80045056 -2147200938
|
||||||
|
* An attempt to ask a container lexicon for all words at once.
|
||||||
|
*/
|
||||||
|
#define SPERR_LEX_REQUIRES_COOKIE MAKE_SAPI_ERROR(0x056)
|
||||||
|
|
||||||
|
/*** SP_STREAM_UNINITIALIZED 0x00045057 282711
|
||||||
|
* An attempt to activate a rule/dictation/etc without calling SetInput
|
||||||
|
* first in the inproc case.
|
||||||
|
*/
|
||||||
|
#define SP_STREAM_UNINITIALIZED MAKE_SAPI_SCODE(0x057)
|
||||||
|
|
||||||
|
|
||||||
|
// Error x058 is not used in SAPI 5.0
|
||||||
|
|
||||||
|
|
||||||
|
/*** SPERR_UNSUPPORTED_LANG 0x80045059 -2147200935
|
||||||
|
* The requested language is not supported.
|
||||||
|
*/
|
||||||
|
#define SPERR_UNSUPPORTED_LANG MAKE_SAPI_ERROR(0x059)
|
||||||
|
|
||||||
|
/*** SPERR_VOICE_PAUSED 0x8004505a -2147200934
|
||||||
|
* The operation cannot be performed because the voice is currently paused.
|
||||||
|
*/
|
||||||
|
#define SPERR_VOICE_PAUSED MAKE_SAPI_ERROR(0x05a)
|
||||||
|
|
||||||
|
/*** SPERR_AUDIO_BUFFER_UNDERFLOW 0x8004505b -2147200933
|
||||||
|
* This will only be returned on input (read) streams when the real time audio device
|
||||||
|
* stops returning data for a long period of time.
|
||||||
|
*/
|
||||||
|
#define SPERR_AUDIO_BUFFER_UNDERFLOW MAKE_SAPI_ERROR(0x05b)
|
||||||
|
|
||||||
|
/*** SPERR_AUDIO_STOPPED_UNEXPECTEDLY 0x8004505c -2147200932
|
||||||
|
* An audio device stopped returning data from the Read() method even though it was in
|
||||||
|
* the run state. This error is only returned in the END_SR_STREAM event.
|
||||||
|
*/
|
||||||
|
#define SPERR_AUDIO_STOPPED_UNEXPECTEDLY MAKE_SAPI_ERROR(0x05c)
|
||||||
|
|
||||||
|
/*** SPERR_NO_WORD_PRONUNCIATION 0x8004505d -2147200931
|
||||||
|
* The SR engine is unable to add this word to a grammar. The application may need to supply
|
||||||
|
* an explicit pronunciation for this word.
|
||||||
|
*/
|
||||||
|
#define SPERR_NO_WORD_PRONUNCIATION MAKE_SAPI_ERROR(0x05d)
|
||||||
|
|
||||||
|
/*** SPERR_ALTERNATES_WOULD_BE_INCONSISTENT 0x8004505e -2147200930
|
||||||
|
* An attempt to call ScaleAudio on a recognition result having previously
|
||||||
|
* called GetAlternates. Allowing the call to succeed would result in
|
||||||
|
* the previously created alternates located in incorrect audio stream positions.
|
||||||
|
*/
|
||||||
|
#define SPERR_ALTERNATES_WOULD_BE_INCONSISTENT MAKE_SAPI_ERROR(0x05e)
|
||||||
|
|
||||||
|
/*** SPERR_NOT_SUPPORTED_FOR_SHARED_RECOGNIZER 0x8004505f -2147200929
|
||||||
|
* The method called is not supported for the shared recognizer.
|
||||||
|
* For example, ISpRecognizer::GetInputStream().
|
||||||
|
*/
|
||||||
|
#define SPERR_NOT_SUPPORTED_FOR_SHARED_RECOGNIZER MAKE_SAPI_ERROR(0x05f)
|
||||||
|
|
||||||
|
/*** SPERR_TIMEOUT 0x80045060 -2147200928
|
||||||
|
* A task could not complete because the SR engine had timed out.
|
||||||
|
*/
|
||||||
|
#define SPERR_TIMEOUT MAKE_SAPI_ERROR(0x060)
|
||||||
|
|
||||||
|
|
||||||
|
/*** SPERR_REENTER_SYNCHRONIZE 0x80045061 -2147200927
|
||||||
|
* A SR engine called synchronize while inside of a synchronize call.
|
||||||
|
*/
|
||||||
|
#define SPERR_REENTER_SYNCHRONIZE MAKE_SAPI_ERROR(0x061)
|
||||||
|
|
||||||
|
/*** SPERR_STATE_WITH_NO_ARCS 0x80045062 -2147200926
|
||||||
|
* The grammar contains a node no arcs.
|
||||||
|
*/
|
||||||
|
#define SPERR_STATE_WITH_NO_ARCS MAKE_SAPI_ERROR(0x062)
|
||||||
|
|
||||||
|
/*** SPERR_NOT_ACTIVE_SESSION 0x80045063 -2147200925
|
||||||
|
* Neither audio output and input is supported for non-active console sessions.
|
||||||
|
*/
|
||||||
|
#define SPERR_NOT_ACTIVE_SESSION MAKE_SAPI_ERROR(0x063)
|
||||||
|
|
||||||
|
/*** SPERR_ALREADY_DELETED 0x80045064 -2147200924
|
||||||
|
* The object is a stale reference and is invalid to use.
|
||||||
|
* For example having a ISpeechGrammarRule object reference and then calling
|
||||||
|
* ISpeechRecoGrammar::Reset() will cause the rule object to be invalidated.
|
||||||
|
* Calling any methods after this will result in this error.
|
||||||
|
*/
|
||||||
|
#define SPERR_ALREADY_DELETED MAKE_SAPI_ERROR(0x064)
|
||||||
|
|
||||||
|
/*** SP_AUDIO_STOPPED 0x00045065 282725
|
||||||
|
* This can be returned from Read or Write calls audio streams when the stream is stopped.
|
||||||
|
*/
|
||||||
|
#define SP_AUDIO_STOPPED MAKE_SAPI_SCODE(0x065)
|
||||||
|
|
||||||
|
#endif //--- This must be the last line in the file
|
605
mp/src/utils/sapi51/Include/speventq.h
Normal file
605
mp/src/utils/sapi51/Include/speventq.h
Normal file
@ -0,0 +1,605 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* SPEventQ.h *
|
||||||
|
*------------*
|
||||||
|
* Description:
|
||||||
|
* This is the header file for the SAPI5 event queue implementation.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*******************************************************************************/
|
||||||
|
#ifndef SPEventQ_h
|
||||||
|
#define SPEventQ_h
|
||||||
|
|
||||||
|
#ifndef SPHelper_h
|
||||||
|
#include <SPHelper.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPCollec_h
|
||||||
|
#include <SPCollec.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=== Inline helpers for copying and deleting events ============================
|
||||||
|
|
||||||
|
|
||||||
|
//=== Class definition ==========================================================
|
||||||
|
|
||||||
|
class CSpEventNode : public CSpEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSpEventNode * m_pNext;
|
||||||
|
static LONG Compare(const CSpEventNode * p1, const CSpEventNode *p2)
|
||||||
|
{
|
||||||
|
// Assumes offsets DO or DO NOT reset when stream number changes
|
||||||
|
if (p1->ulStreamNum < p2->ulStreamNum)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (p1->ulStreamNum > p2->ulStreamNum)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (p1->ullAudioStreamOffset < p2->ullAudioStreamOffset)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (p1->ullAudioStreamOffset > p2->ullAudioStreamOffset)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef CSpBasicQueue<CSpEventNode, TRUE, TRUE> CSpEventList;
|
||||||
|
|
||||||
|
#define DECLARE_SPNOTIFYSOURCE_METHODS(T) \
|
||||||
|
STDMETHODIMP SetNotifySink(ISpNotifySink * pNotifySink) \
|
||||||
|
{ return T._SetNotifySink(pNotifySink); } \
|
||||||
|
STDMETHODIMP SetNotifyWindowMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) \
|
||||||
|
{ return T._SetNotifyWindowMessage(hWnd, Msg, wParam, lParam); } \
|
||||||
|
STDMETHODIMP SetNotifyCallbackFunction(SPNOTIFYCALLBACK * pfnCallback, WPARAM wParam, LPARAM lParam) \
|
||||||
|
{ return T._SetNotifyCallbackFunction(pfnCallback, wParam, lParam); } \
|
||||||
|
STDMETHODIMP SetNotifyCallbackInterface(ISpNotifyCallback * pSpCallback, WPARAM wParam, LPARAM lParam) \
|
||||||
|
{ return T._SetNotifyCallbackInterface(pSpCallback, wParam, lParam); } \
|
||||||
|
STDMETHODIMP SetNotifyWin32Event() \
|
||||||
|
{ return T._SetNotifyWin32Event(); } \
|
||||||
|
STDMETHODIMP WaitForNotifyEvent(DWORD dwMilliseconds) \
|
||||||
|
{ return T._WaitForNotifyEvent(dwMilliseconds); } \
|
||||||
|
STDMETHODIMP_(HANDLE) GetNotifyEventHandle() \
|
||||||
|
{ return T._GetNotifyEventHandle(); }
|
||||||
|
|
||||||
|
#define DECLARE_SPEVENTSOURCE_METHODS(T) \
|
||||||
|
DECLARE_SPNOTIFYSOURCE_METHODS(T) \
|
||||||
|
STDMETHODIMP SetInterest(ULONGLONG ullEventInterest, ULONGLONG ullQueuedInterest) \
|
||||||
|
{ return T._SetInterest(ullEventInterest, ullQueuedInterest); } \
|
||||||
|
STDMETHODIMP GetEvents(ULONG ulCount, SPEVENT* pEventArray, ULONG * pulFetched) \
|
||||||
|
{ return T._GetEvents(ulCount, pEventArray, pulFetched); } \
|
||||||
|
STDMETHODIMP GetInfo(SPEVENTSOURCEINFO *pInfo) \
|
||||||
|
{ return T._GetInfo(pInfo); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CSpEventSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSpEventSource(CComObjectRootEx<CComMultiThreadModel> * pParent) :
|
||||||
|
m_pParent(pParent)
|
||||||
|
{
|
||||||
|
m_ullEventInterest = 0; m_ullQueuedInterest = 0;
|
||||||
|
m_ulStreamNum = 0;
|
||||||
|
}
|
||||||
|
HRESULT _SetNotifySink(ISpNotifySink * pNotifySink);
|
||||||
|
HRESULT _SetNotifyWindowMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
HRESULT _SetNotifyCallbackFunction(SPNOTIFYCALLBACK * pfnCallback, WPARAM wParam, LPARAM lParam);
|
||||||
|
HRESULT _SetNotifyCallbackInterface(ISpNotifyCallback * pSpCallback, WPARAM wParam, LPARAM lParam);
|
||||||
|
HRESULT _SetNotifyWin32Event();
|
||||||
|
HRESULT _WaitForNotifyEvent(DWORD dwMilliseconds);
|
||||||
|
HANDLE _GetNotifyEventHandle();
|
||||||
|
|
||||||
|
HRESULT _SetInterest(ULONGLONG ullEventInterest , ULONGLONG ullQueuedInterest);
|
||||||
|
HRESULT _GetEvents( ULONG ulCount, SPEVENT* pEventArray, ULONG * pulFetched );
|
||||||
|
HRESULT _GetInfo(SPEVENTSOURCEINFO *pInfo );
|
||||||
|
|
||||||
|
/*--- Non interface methods ---*/
|
||||||
|
HRESULT _CompleteEvents( ULONGLONG ullPos = 0xFFFFFFFFFFFFFFFF );
|
||||||
|
inline void _MoveAllToFreeList(CSpEventList * pList);
|
||||||
|
inline void _RemoveAllEvents();
|
||||||
|
inline HRESULT _AddEvent(const SPEVENT & Event);
|
||||||
|
inline HRESULT _AddEvents(const SPEVENT* pEventArray, ULONG ulCount);
|
||||||
|
inline HRESULT _DeserializeAndAddEvent(const BYTE * pBuffer, ULONG * pcbUsed);
|
||||||
|
inline HRESULT _GetStreamNumber(const ULONGLONG ullAudioOffset, ULONG *pulStreamNum);
|
||||||
|
//=== Data members ==============================
|
||||||
|
public:
|
||||||
|
ULONGLONG m_ullEventInterest;
|
||||||
|
ULONGLONG m_ullQueuedInterest;
|
||||||
|
ULONG m_ulStreamNum;
|
||||||
|
CSpEventList m_PendingList;
|
||||||
|
CSpEventList m_CompletedList;
|
||||||
|
CSpEventList m_FreeList;
|
||||||
|
CComPtr<ISpNotifySink> m_cpNotifySink;
|
||||||
|
CComPtr<ISpNotifyTranslator> m_cpEventTranslator; // If non-NULL then Win32 events being used
|
||||||
|
CComObjectRootEx<CComMultiThreadModel> * m_pParent;
|
||||||
|
CComAutoCriticalSection m_NotifyObjChangeCrit; // Critical section used to make sure that
|
||||||
|
// the notify object (m_cpNotifySink) not changed
|
||||||
|
// while waiting on it.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//=== Inlines =========================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// WARNING: If this logic changes, you will need to change the logic in SetNotifyWin32Event also.
|
||||||
|
//
|
||||||
|
inline HRESULT CSpEventSource::_SetNotifySink(ISpNotifySink * pNotifySink)
|
||||||
|
{
|
||||||
|
if (SP_IS_BAD_OPTIONAL_INTERFACE_PTR(pNotifySink))
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pParent->Lock();
|
||||||
|
m_NotifyObjChangeCrit.Lock();
|
||||||
|
m_cpEventTranslator.Release();
|
||||||
|
m_cpNotifySink = pNotifySink;
|
||||||
|
if (m_cpNotifySink && m_CompletedList.GetHead())
|
||||||
|
{
|
||||||
|
m_cpNotifySink->Notify();
|
||||||
|
}
|
||||||
|
m_NotifyObjChangeCrit.Unlock();
|
||||||
|
m_pParent->Unlock();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CSpEventSource::_SetNotifyWindowMessage *
|
||||||
|
*-----------------------------------------*
|
||||||
|
* Description:
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*
|
||||||
|
********************************************************************* RAL ***/
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_SetNotifyWindowMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
SPDBG_FUNC("CSpEventSource::_SetNotifyWindowMessage");
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
CComPtr<ISpNotifyTranslator> cpTranslator;
|
||||||
|
hr = cpTranslator.CoCreateInstance(CLSID_SpNotifyTranslator);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpTranslator->InitWindowMessage(hWnd, Msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = _SetNotifySink(cpTranslator);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
* CSpEventSource::_SetNotifyCallbackFunction *
|
||||||
|
*--------------------------------------------*
|
||||||
|
* Description:
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*
|
||||||
|
********************************************************************* RAL ***/
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_SetNotifyCallbackFunction(SPNOTIFYCALLBACK * pfnCallback, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
SPDBG_FUNC("CSpEventSource::_SetNotifyCallbackFunction");
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
CComPtr<ISpNotifyTranslator> cpTranslator;
|
||||||
|
hr = cpTranslator.CoCreateInstance(CLSID_SpNotifyTranslator);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpTranslator->InitCallback(pfnCallback, wParam, lParam);
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = _SetNotifySink(cpTranslator);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
* CSpEventSource::_SetNotifyCallbackInterface *
|
||||||
|
*---------------------------------------------*
|
||||||
|
* Description:
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*
|
||||||
|
********************************************************************* RAL ***/
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_SetNotifyCallbackInterface(ISpNotifyCallback * pSpCallback, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
SPDBG_FUNC("CSpEventSource::_SetNotifyCallbackInterface");
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
CComPtr<ISpNotifyTranslator> cpTranslator;
|
||||||
|
hr = cpTranslator.CoCreateInstance(CLSID_SpNotifyTranslator);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpTranslator->InitSpNotifyCallback(pSpCallback, wParam, lParam);
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = _SetNotifySink(cpTranslator);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
* CSpEventSource::_SetNotifyWin32Event *
|
||||||
|
*--------------------------------------*
|
||||||
|
* Description:
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*
|
||||||
|
********************************************************************* RAL ***/
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_SetNotifyWin32Event(void)
|
||||||
|
{
|
||||||
|
SPDBG_FUNC("CSpEventSource::_SetNotifyWin32Event");
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
CComPtr<ISpNotifyTranslator> cpTranslator;
|
||||||
|
hr = cpTranslator.CoCreateInstance(CLSID_SpNotifyTranslator);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpTranslator->InitWin32Event(NULL, TRUE);
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// In this case we do NOT call _SetNotify sink since we want to set the cpEventTranslator
|
||||||
|
//
|
||||||
|
m_pParent->Lock();
|
||||||
|
m_NotifyObjChangeCrit.Lock();
|
||||||
|
m_cpEventTranslator = cpTranslator;
|
||||||
|
m_cpNotifySink = cpTranslator;
|
||||||
|
if (m_cpNotifySink && m_CompletedList.GetHead())
|
||||||
|
{
|
||||||
|
m_cpNotifySink->Notify();
|
||||||
|
}
|
||||||
|
m_NotifyObjChangeCrit.Unlock();
|
||||||
|
m_pParent->Unlock();
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
* CSpEventSource::_WaitForNotifyEvent *
|
||||||
|
*-------------------------------------*
|
||||||
|
* Description:
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*
|
||||||
|
********************************************************************* RAL ***/
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_WaitForNotifyEvent(DWORD dwMilliseconds)
|
||||||
|
{
|
||||||
|
SPDBG_FUNC("CSpEventSource::_WaitForNotifyEvent");
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
m_NotifyObjChangeCrit.Lock();
|
||||||
|
if (m_cpEventTranslator)
|
||||||
|
{
|
||||||
|
hr = m_cpEventTranslator->Wait(dwMilliseconds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_cpNotifySink)
|
||||||
|
{
|
||||||
|
hr = SPERR_ALREADY_INITIALIZED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = _SetNotifyWin32Event();
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = m_cpEventTranslator->Wait(dwMilliseconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_NotifyObjChangeCrit.Unlock();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
* CSpEventSource::_GetNotifyEventHandle *
|
||||||
|
*---------------------------------------*
|
||||||
|
* Description:
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*
|
||||||
|
********************************************************************* RAL ***/
|
||||||
|
|
||||||
|
inline HANDLE CSpEventSource::_GetNotifyEventHandle()
|
||||||
|
{
|
||||||
|
HANDLE h = NULL;
|
||||||
|
SPDBG_FUNC("CSpEventSource::_GetNotifyEventHandle");
|
||||||
|
m_NotifyObjChangeCrit.Lock();
|
||||||
|
if (!m_cpNotifySink)
|
||||||
|
{
|
||||||
|
_SetNotifyWin32Event();
|
||||||
|
}
|
||||||
|
if (m_cpEventTranslator)
|
||||||
|
{
|
||||||
|
h = m_cpEventTranslator->GetEventHandle();
|
||||||
|
}
|
||||||
|
m_NotifyObjChangeCrit.Unlock();
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_SetInterest( ULONGLONG ullEventInterest, ULONGLONG ullQueuedInterest )
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
m_pParent->Lock();
|
||||||
|
|
||||||
|
if(ullEventInterest && SPFEI_FLAGCHECK != (ullEventInterest & SPFEI_FLAGCHECK))
|
||||||
|
{
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else if(ullQueuedInterest && SPFEI_FLAGCHECK != (ullQueuedInterest & SPFEI_FLAGCHECK))
|
||||||
|
{
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else if ((ullQueuedInterest | ullEventInterest) != ullEventInterest)
|
||||||
|
{
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ullEventInterest = ullEventInterest;
|
||||||
|
m_ullQueuedInterest = ullQueuedInterest;
|
||||||
|
}
|
||||||
|
m_pParent->Unlock();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Same as AddEvents except: No param validation, and caller must take the critical section
|
||||||
|
// prior to calling.
|
||||||
|
//
|
||||||
|
inline HRESULT CSpEventSource::_AddEvents( const SPEVENT* pEventArray, ULONG ulCount )
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
for( ULONG i = 0; i < ulCount && SUCCEEDED(hr = _AddEvent(pEventArray[i])); ++i ) {}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_AddEvent(const SPEVENT & Event)
|
||||||
|
{
|
||||||
|
SPDBG_ASSERT(Event.eEventId < 64);
|
||||||
|
SPDBG_ASSERT(Event.elParamType == SPET_LPARAM_IS_UNDEFINED ||
|
||||||
|
Event.elParamType == SPET_LPARAM_IS_TOKEN ||
|
||||||
|
Event.elParamType == SPET_LPARAM_IS_OBJECT ||
|
||||||
|
Event.elParamType == SPET_LPARAM_IS_POINTER ||
|
||||||
|
Event.elParamType == SPET_LPARAM_IS_STRING);
|
||||||
|
#ifdef _DEBUG
|
||||||
|
if (Event.eEventId == SPEI_VOICE_CHANGE)
|
||||||
|
{
|
||||||
|
SPDBG_ASSERT(Event.elParamType == SPET_LPARAM_IS_TOKEN);
|
||||||
|
}
|
||||||
|
else if (Event.eEventId == SPEI_RECOGNITION || Event.eEventId == SPEI_FALSE_RECOGNITION || Event.eEventId == SPEI_HYPOTHESIS)
|
||||||
|
{
|
||||||
|
SPDBG_ASSERT(Event.elParamType == SPET_LPARAM_IS_OBJECT);
|
||||||
|
}
|
||||||
|
else if (Event.eEventId ==SPEI_REQUEST_UI || Event.eEventId == SPEI_TTS_BOOKMARK)
|
||||||
|
{
|
||||||
|
SPDBG_ASSERT(Event.elParamType == SPET_LPARAM_IS_STRING);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( (1i64 << Event.eEventId) & m_ullEventInterest )
|
||||||
|
{
|
||||||
|
CSpEventNode *pNode = m_FreeList.RemoveHead();
|
||||||
|
if (pNode == NULL)
|
||||||
|
{
|
||||||
|
pNode = new CSpEventNode();
|
||||||
|
if (pNode == NULL)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pNode->CopyFrom(&Event);
|
||||||
|
m_PendingList.InsertSorted(pNode);
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::
|
||||||
|
_DeserializeAndAddEvent(const BYTE *pBuffer, ULONG * pcbUsed)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
const SPEVENT * pSrcEvent = (const SPEVENT *)pBuffer;
|
||||||
|
SPDBG_ASSERT(pSrcEvent->eEventId < 64);
|
||||||
|
if ( (1i64 << pSrcEvent->eEventId) & m_ullEventInterest )
|
||||||
|
{
|
||||||
|
CSpEventNode *pNode = m_FreeList.RemoveHead();
|
||||||
|
if (pNode == NULL)
|
||||||
|
{
|
||||||
|
pNode = new CSpEventNode();
|
||||||
|
if (pNode == NULL)
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pNode->Deserialize(((const SPSERIALIZEDEVENT64 *)(pBuffer)), pcbUsed);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
m_PendingList.InsertSorted(pNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_FreeList.InsertHead(pNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// WCE compiler does not work propertly with template
|
||||||
|
#ifndef _WIN32_WCE
|
||||||
|
*pcbUsed = SpEventSerializeSize<SPSERIALIZEDEVENT64>(pSrcEvent);
|
||||||
|
#else
|
||||||
|
*pcbUsed = SpEventSerializeSize(pSrcEvent, sizeof(SPSERIALIZEDEVENT64));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_GetEvents( ULONG ulCount, SPEVENT* pEventArray, ULONG *pulFetched )
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
m_pParent->Lock();
|
||||||
|
if( SPIsBadWritePtr( pEventArray, sizeof( SPEVENT ) * ulCount ) ||
|
||||||
|
SP_IS_BAD_OPTIONAL_WRITE_PTR(pulFetched) )
|
||||||
|
{
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ULONG ulCopied = 0;
|
||||||
|
ULONG ulRemaining = ulCount;
|
||||||
|
CSpEventNode * pCur = m_CompletedList.m_pHead;
|
||||||
|
CSpEventNode * pLastCopied = NULL;
|
||||||
|
while (ulRemaining && pCur)
|
||||||
|
{
|
||||||
|
pCur->Detach(pEventArray + ulCopied);
|
||||||
|
pLastCopied = pCur;
|
||||||
|
ulCopied++;
|
||||||
|
pCur = pCur->m_pNext;
|
||||||
|
ulRemaining--;
|
||||||
|
}
|
||||||
|
if (ulCopied)
|
||||||
|
{
|
||||||
|
if (m_FreeList.m_pHead == NULL)
|
||||||
|
{
|
||||||
|
m_FreeList.m_pTail = pLastCopied;
|
||||||
|
}
|
||||||
|
pLastCopied->m_pNext = m_FreeList.m_pHead;
|
||||||
|
m_FreeList.m_pHead = m_CompletedList.m_pHead;
|
||||||
|
m_CompletedList.m_pHead = pCur;
|
||||||
|
m_CompletedList.m_cElements -= ulCopied;
|
||||||
|
m_FreeList.m_cElements += ulCopied;
|
||||||
|
}
|
||||||
|
if (ulCopied < ulCount)
|
||||||
|
{
|
||||||
|
hr = S_FALSE;
|
||||||
|
}
|
||||||
|
if (pulFetched)
|
||||||
|
{
|
||||||
|
*pulFetched = ulCopied;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_pParent->Unlock();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_GetInfo( SPEVENTSOURCEINFO * pInfo )
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
m_pParent->Lock();
|
||||||
|
if( SP_IS_BAD_WRITE_PTR( pInfo ) )
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pInfo->ulCount = m_CompletedList.GetCount();
|
||||||
|
pInfo->ullEventInterest = m_ullEventInterest;
|
||||||
|
pInfo->ullQueuedInterest= m_ullQueuedInterest;
|
||||||
|
}
|
||||||
|
m_pParent->Unlock();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// The caller must call this function with the critical section owned
|
||||||
|
//
|
||||||
|
inline HRESULT CSpEventSource::_CompleteEvents( ULONGLONG ullPos )
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (m_PendingList.m_pHead && m_PendingList.m_pHead->ullAudioStreamOffset <= ullPos)
|
||||||
|
{
|
||||||
|
BOOL bNotify = FALSE;
|
||||||
|
while (m_PendingList.m_pHead &&
|
||||||
|
m_PendingList.m_pHead->ullAudioStreamOffset <= ullPos)
|
||||||
|
{
|
||||||
|
CSpEventNode *pNode = m_PendingList.RemoveHead();
|
||||||
|
if(pNode->ulStreamNum != m_ulStreamNum)
|
||||||
|
{
|
||||||
|
m_ulStreamNum = pNode->ulStreamNum;
|
||||||
|
}
|
||||||
|
if ( (1i64 << pNode->eEventId) & m_ullEventInterest )
|
||||||
|
{
|
||||||
|
bNotify = TRUE;
|
||||||
|
//
|
||||||
|
// NOTE: If we're forwarding events to an event sink then we'll only
|
||||||
|
// pay attention to the Interest flags. If we're going to notify, then
|
||||||
|
// we'll only queue completed events that the user has explicitly asked
|
||||||
|
// us to store as completed events.
|
||||||
|
//
|
||||||
|
if ( (1i64 << pNode->eEventId) & m_ullQueuedInterest )
|
||||||
|
{
|
||||||
|
m_CompletedList.InsertSorted(pNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pNode->Clear();
|
||||||
|
m_FreeList.InsertHead(pNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pNode->Clear();
|
||||||
|
m_FreeList.InsertHead(pNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bNotify && m_cpNotifySink)
|
||||||
|
{
|
||||||
|
hr = m_cpNotifySink->Notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline void CSpEventSource::_MoveAllToFreeList(CSpEventList * pList)
|
||||||
|
{
|
||||||
|
CSpEventNode * pNode;
|
||||||
|
while ((pNode = pList->RemoveHead()) != NULL)
|
||||||
|
{
|
||||||
|
pNode->Clear();
|
||||||
|
m_FreeList.InsertHead(pNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void CSpEventSource::_RemoveAllEvents( )
|
||||||
|
{
|
||||||
|
m_pParent->Lock();
|
||||||
|
|
||||||
|
_MoveAllToFreeList(&m_CompletedList);
|
||||||
|
_MoveAllToFreeList(&m_PendingList);
|
||||||
|
m_pParent->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT CSpEventSource::_GetStreamNumber(const ULONGLONG ullAudioOffset, ULONG *pulStreamNum)
|
||||||
|
{
|
||||||
|
CSpEventNode *pNode = m_PendingList.m_pHead;
|
||||||
|
*pulStreamNum = m_ulStreamNum;
|
||||||
|
for(;pNode && pNode->ullAudioStreamOffset <= ullAudioOffset; pNode = pNode->m_pNext)
|
||||||
|
{
|
||||||
|
*pulStreamNum = pNode->ulStreamNum;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //--- This must be the last line in this file
|
2754
mp/src/utils/sapi51/Include/sphelper.h
Normal file
2754
mp/src/utils/sapi51/Include/sphelper.h
Normal file
File diff suppressed because it is too large
Load Diff
253
mp/src/utils/sapi51/Include/spuihelp.h
Normal file
253
mp/src/utils/sapi51/Include/spuihelp.h
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* SPUIHelp.h *
|
||||||
|
*------------*
|
||||||
|
* Description:
|
||||||
|
* This is the header file for user-interface helper functions. Note that
|
||||||
|
* unlike SpHelper.H, this file requires the use of ATL.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef SPUIHelp_h
|
||||||
|
#define SPUIHelp_h
|
||||||
|
|
||||||
|
#ifndef __sapi_h__
|
||||||
|
#include <sapi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPError_h
|
||||||
|
#include <SPError.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPDebug_h
|
||||||
|
#include <SPDebug.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPHelper_h
|
||||||
|
#include <SPHelper.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ATLBASE_H__
|
||||||
|
#include <ATLBASE.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ATLCONV_H__
|
||||||
|
#include <ATLCONV.H>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
********************************************************************* RAL ***/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dont call this function directly. Use SpInitTokenComboBox or SpInitTokenListBox.
|
||||||
|
//
|
||||||
|
inline HRESULT SpInitTokenList(UINT MsgAddString, UINT MsgSetItemData, UINT MsgSetCurSel,
|
||||||
|
HWND hwnd, const WCHAR * pszCatName,
|
||||||
|
const WCHAR * pszRequiredAttrib, const WCHAR * pszOptionalAttrib)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
ISpObjectToken * pToken; // NOTE: Not a CComPtr! Be Careful.
|
||||||
|
CComPtr<IEnumSpObjectTokens> cpEnum;
|
||||||
|
hr = SpEnumTokens(pszCatName, pszRequiredAttrib, pszOptionalAttrib, &cpEnum);
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
bool fSetDefault = false;
|
||||||
|
while (cpEnum->Next(1, &pToken, NULL) == S_OK)
|
||||||
|
{
|
||||||
|
CSpDynamicString dstrDesc;
|
||||||
|
hr = SpGetDescription(pToken, &dstrDesc);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
USES_CONVERSION;
|
||||||
|
LRESULT i = ::SendMessage(hwnd, MsgAddString, 0, (LPARAM)W2T(dstrDesc));
|
||||||
|
if (i == CB_ERR || i == CB_ERRSPACE) // Note: CB_ and LB_ errors are identical values...
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
::SendMessage(hwnd, MsgSetItemData, i, (LPARAM)pToken);
|
||||||
|
if (!fSetDefault)
|
||||||
|
{
|
||||||
|
::SendMessage(hwnd, MsgSetCurSel, i, 0);
|
||||||
|
fSetDefault = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
pToken->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = SPERR_NO_MORE_ITEMS;
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpInitTokenComboBox(HWND hwnd, const WCHAR * pszCatName,
|
||||||
|
const WCHAR * pszRequiredAttrib = NULL, const WCHAR * pszOptionalAttrib = NULL)
|
||||||
|
{
|
||||||
|
return SpInitTokenList(CB_ADDSTRING, CB_SETITEMDATA, CB_SETCURSEL, hwnd, pszCatName, pszRequiredAttrib, pszOptionalAttrib);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpInitTokenListBox(HWND hwnd, const WCHAR * pszCatName,
|
||||||
|
const WCHAR * pszRequiredAttrib = NULL, const WCHAR * pszOptionalAttrib = NULL)
|
||||||
|
{
|
||||||
|
return SpInitTokenList(LB_ADDSTRING, LB_SETITEMDATA, LB_SETCURSEL, hwnd, pszCatName, pszRequiredAttrib, pszOptionalAttrib);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dont call this function directly. Use SpDestoyTokenComboBox or SpDestroyTokenListBox.
|
||||||
|
//
|
||||||
|
inline void SpDestroyTokenList(UINT MsgGetCount, UINT MsgGetItemData, HWND hwnd)
|
||||||
|
{
|
||||||
|
LRESULT c = ::SendMessage(hwnd, MsgGetCount, 0, 0);
|
||||||
|
for (LRESULT i = 0; i < c; i++)
|
||||||
|
{
|
||||||
|
IUnknown * pUnkObj = (IUnknown *)::SendMessage(hwnd, MsgGetItemData, i, 0);
|
||||||
|
if (pUnkObj)
|
||||||
|
{
|
||||||
|
pUnkObj->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SpDestroyTokenComboBox(HWND hwnd)
|
||||||
|
{
|
||||||
|
SpDestroyTokenList(CB_GETCOUNT, CB_GETITEMDATA, hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SpDestroyTokenListBox(HWND hwnd)
|
||||||
|
{
|
||||||
|
SpDestroyTokenList(LB_GETCOUNT, LB_GETITEMDATA, hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline ISpObjectToken * SpGetComboBoxToken(HWND hwnd, WPARAM Index)
|
||||||
|
{
|
||||||
|
return (ISpObjectToken *)::SendMessage(hwnd, CB_GETITEMDATA, Index, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ISpObjectToken * SpGetListBoxToken(HWND hwnd, WPARAM Index)
|
||||||
|
{
|
||||||
|
return (ISpObjectToken *)::SendMessage(hwnd, LB_GETITEMDATA, Index, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ISpObjectToken * SpGetCurSelComboBoxToken(HWND hwnd)
|
||||||
|
{
|
||||||
|
LRESULT i = ::SendMessage(hwnd, CB_GETCURSEL, 0, 0);
|
||||||
|
return (i == CB_ERR) ? NULL : SpGetComboBoxToken(hwnd, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ISpObjectToken * SpGetCurSelListBoxToken(HWND hwnd)
|
||||||
|
{
|
||||||
|
LRESULT i = ::SendMessage(hwnd, LB_GETCURSEL, 0, 0);
|
||||||
|
return (i == LB_ERR) ? NULL : SpGetListBoxToken(hwnd, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Don't call this directly. Use SpUpdateCurSelComboBoxToken or SpUpdateCurSelListBoxToken
|
||||||
|
//
|
||||||
|
inline HRESULT SpUpdateCurSelToken(UINT MsgDelString, UINT MsgInsertString, UINT MsgGetItemData, UINT MsgSetItemData, UINT MsgGetCurSel, UINT MsgSetCurSel,
|
||||||
|
HWND hwnd)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
LRESULT i = ::SendMessage(hwnd, MsgGetCurSel, 0, 0);
|
||||||
|
if (i != CB_ERR)
|
||||||
|
{
|
||||||
|
ISpObjectToken * pToken = (ISpObjectToken *)::SendMessage(hwnd, MsgGetItemData, i, 0);
|
||||||
|
CSpDynamicString dstrDesc;
|
||||||
|
hr = SpGetDescription(pToken, &dstrDesc);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
USES_CONVERSION;
|
||||||
|
::SendMessage(hwnd, MsgDelString, i, 0);
|
||||||
|
::SendMessage(hwnd, MsgInsertString, i, (LPARAM)W2T(dstrDesc));
|
||||||
|
::SendMessage(hwnd, MsgSetItemData, i, (LPARAM)pToken);
|
||||||
|
::SendMessage(hwnd, MsgSetCurSel, i, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpUpdateCurSelComboBoxToken(HWND hwnd)
|
||||||
|
{
|
||||||
|
return SpUpdateCurSelToken(CB_DELETESTRING, CB_INSERTSTRING, CB_GETITEMDATA, CB_SETITEMDATA, CB_GETCURSEL, CB_SETCURSEL, hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpUpdateCurSelListBoxToken(HWND hwnd)
|
||||||
|
{
|
||||||
|
return SpUpdateCurSelToken(LB_DELETESTRING, LB_INSERTSTRING, LB_GETITEMDATA, LB_SETITEMDATA, LB_GETCURSEL, LB_SETCURSEL, hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpAddTokenToList(UINT MsgAddString, UINT MsgSetItemData, UINT MsgSetCurSel, HWND hwnd, ISpObjectToken * pToken)
|
||||||
|
{
|
||||||
|
CSpDynamicString dstrDesc;
|
||||||
|
HRESULT hr = SpGetDescription(pToken, &dstrDesc);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
USES_CONVERSION;
|
||||||
|
LRESULT i = ::SendMessage(hwnd, MsgAddString, 0, (LPARAM)W2T(dstrDesc));
|
||||||
|
if (i == CB_ERR || i == CB_ERRSPACE) // Note: CB_ and LB_ errors are identical values...
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
::SendMessage(hwnd, MsgSetItemData, i, (LPARAM)pToken);
|
||||||
|
::SendMessage(hwnd, MsgSetCurSel, i, 0);
|
||||||
|
pToken->AddRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpAddTokenToComboBox(HWND hwnd, ISpObjectToken * pToken)
|
||||||
|
{
|
||||||
|
return SpAddTokenToList(CB_ADDSTRING, CB_SETITEMDATA, CB_SETCURSEL, hwnd, pToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpAddTokenToListBox(HWND hwnd, ISpObjectToken * pToken)
|
||||||
|
{
|
||||||
|
return SpAddTokenToList(LB_ADDSTRING, LB_SETITEMDATA, LB_SETCURSEL, hwnd, pToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline HRESULT SpDeleteCurSelToken(UINT MsgGetCurSel, UINT MsgSetCurSel, UINT MsgGetItemData, UINT MsgDeleteString, HWND hwnd)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
LRESULT i = ::SendMessage(hwnd, MsgGetCurSel, 0, 0);
|
||||||
|
if (i == CB_ERR)
|
||||||
|
{
|
||||||
|
hr = S_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ISpObjectToken * pToken = (ISpObjectToken *)::SendMessage(hwnd, MsgGetItemData, i, 0);
|
||||||
|
if (pToken)
|
||||||
|
{
|
||||||
|
pToken->Release();
|
||||||
|
}
|
||||||
|
::SendMessage(hwnd, MsgDeleteString, i, 0);
|
||||||
|
::SendMessage(hwnd, MsgSetCurSel, i, 0);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpDeleteCurSelComboBoxToken(HWND hwnd)
|
||||||
|
{
|
||||||
|
return SpDeleteCurSelToken(CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_DELETESTRING, hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpDeleteCurSelListBoxToken(HWND hwnd)
|
||||||
|
{
|
||||||
|
return SpDeleteCurSelToken(LB_GETCURSEL, CB_SETCURSEL, LB_GETITEMDATA, LB_DELETESTRING, hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #ifndef SPUIHelp_h -- This must be the last line in the file */
|
193
mp/src/utils/sapi51/Samples/CPP/Common/componentversiondlg.cpp
Normal file
193
mp/src/utils/sapi51/Samples/CPP/Common/componentversiondlg.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* ComponentVersionDlg.cpp
|
||||||
|
* This module contains the implementation details of the
|
||||||
|
* "Component Version" dialog that may be accessible from all of the
|
||||||
|
* SAPI SDK samples and tools.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "SapiSDKCommon.h"
|
||||||
|
#include "SapiSDKCommonResources.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* ComponentVersionsDlgProc *
|
||||||
|
*--------------------------*
|
||||||
|
* Description:
|
||||||
|
* The DlgProc for the ComponentVersions dlg. It fills the edit
|
||||||
|
* control with the version & path info of all the .dll's & .exe's
|
||||||
|
* that are loaded by the app that is using us.
|
||||||
|
*
|
||||||
|
* If you wish to have other .dll's & .exe's included, then just
|
||||||
|
* add their names to the s_aszModules_c array. The rest happens
|
||||||
|
* automatically.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* TRUE if have processed the message
|
||||||
|
* FALSE otherwise
|
||||||
|
**********************************************************************/
|
||||||
|
LRESULT CALLBACK ComponentVersionsDlgProc( HWND hDlg, UINT uiMessage, WPARAM wParam, LPARAM lParam )
|
||||||
|
{
|
||||||
|
//--- basic dlg proc switch statement
|
||||||
|
switch( uiMessage )
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
{
|
||||||
|
//--- this array contains the full list of .dll's & .exe's that we will interogate.
|
||||||
|
// just add to this list when you want to add another module to the output
|
||||||
|
static const LPCTSTR s_aszModules_c[] =
|
||||||
|
{
|
||||||
|
_T("dictpad.exe"),
|
||||||
|
_T("reco.exe"),
|
||||||
|
_T("speak.exe"),
|
||||||
|
_T("sapi.cpl"),
|
||||||
|
_T("srsvr.exe"),
|
||||||
|
_T("ttshello.exe"),
|
||||||
|
_T("wavtotext.exe"),
|
||||||
|
_T("wintts.exe"),
|
||||||
|
_T("sapi.dll"),
|
||||||
|
_T("spttseng.dll"),
|
||||||
|
_T("spcwfe.DLL"),
|
||||||
|
_T("spsreng.DLL"),
|
||||||
|
_T("spsr.DLL"),
|
||||||
|
_T("spsrx.DLL"),
|
||||||
|
_T("gramcomp.dll"),
|
||||||
|
_T("Lexicon.dll"),
|
||||||
|
_T("advapi32.DLL"),
|
||||||
|
_T("atl.DLL"),
|
||||||
|
_T("comctl32.DLL"),
|
||||||
|
_T("gdi32.DLL"),
|
||||||
|
_T("icap.DLL"),
|
||||||
|
_T("kernel32.DLL"),
|
||||||
|
_T("lz32.DLL"),
|
||||||
|
_T("mfc42.DLL"),
|
||||||
|
_T("mfc42d.DLL"),
|
||||||
|
_T("mfc42u.DLL"),
|
||||||
|
_T("mfc42ud.DLL"),
|
||||||
|
_T("msasm32.DLL"),
|
||||||
|
_T("msvcrt.DLL"),
|
||||||
|
_T("msxml.DLL"),
|
||||||
|
_T("ntdll.DLL"),
|
||||||
|
_T("ole32.DLL"),
|
||||||
|
_T("oleaut32.DLL"),
|
||||||
|
_T("riched32.DLL"),
|
||||||
|
_T("rpcrt.DLL"),
|
||||||
|
_T("rpcrt4.DLL"),
|
||||||
|
_T("shell32.DLL"),
|
||||||
|
_T("shfolder.DLL"),
|
||||||
|
_T("shlwapi.DLL"),
|
||||||
|
_T("user32.DLL"),
|
||||||
|
_T("urlmon.DLL"),
|
||||||
|
_T("version.DLL"),
|
||||||
|
_T("winmm.DLL")
|
||||||
|
};
|
||||||
|
static const int s_iNumModules_c = sizeof( s_aszModules_c ) / sizeof( s_aszModules_c[ 0 ] );
|
||||||
|
|
||||||
|
TCHAR acFinalBuff[10000];
|
||||||
|
acFinalBuff[ 0 ] = L'\0';
|
||||||
|
|
||||||
|
//--- spin thru all the listed modules to find the ones that are loaded by the current app
|
||||||
|
for( int i = 0; i < s_iNumModules_c; ++i )
|
||||||
|
{
|
||||||
|
//--- main discovery point - is the current module being used, or not
|
||||||
|
HMODULE hModule = GetModuleHandle( s_aszModules_c[ i ] );
|
||||||
|
if( hModule )
|
||||||
|
{
|
||||||
|
//--- the current module is being used, get it's path
|
||||||
|
TCHAR acModulePath[ _MAX_PATH ];
|
||||||
|
DWORD dwSize = GetModuleFileName( hModule, acModulePath, sizeof( acModulePath ) );
|
||||||
|
_ASSERTE( 0 < dwSize );
|
||||||
|
|
||||||
|
//--- now that we have the file, get the version info size from that file. If the
|
||||||
|
// size is non-trivial, then the file contains legitimate version info
|
||||||
|
DWORD dwDummy;
|
||||||
|
dwSize = GetFileVersionInfoSize( const_cast< LPTSTR >( acModulePath ), &dwDummy );
|
||||||
|
TCHAR acBuff[1000];
|
||||||
|
if( 0 < dwSize )
|
||||||
|
{
|
||||||
|
//--- real version info exists for the current module - get it
|
||||||
|
char *pcVersionInfo = new char[ dwSize ];
|
||||||
|
_ASSERTE( NULL != pcVersionInfo );
|
||||||
|
BOOL fSuccess = GetFileVersionInfo( const_cast< LPTSTR >( acModulePath ),
|
||||||
|
0, dwSize, pcVersionInfo );
|
||||||
|
_ASSERTE( fSuccess );
|
||||||
|
|
||||||
|
//--- now convert the version info into something intelligible
|
||||||
|
VS_FIXEDFILEINFO *pFixedVersionInfo;
|
||||||
|
UINT uiFixedVersionSize;
|
||||||
|
fSuccess = VerQueryValue( pcVersionInfo, _T( "\\" ),
|
||||||
|
reinterpret_cast< LPVOID * >( &pFixedVersionInfo ),
|
||||||
|
&uiFixedVersionSize );
|
||||||
|
_ASSERTE( fSuccess );
|
||||||
|
|
||||||
|
//--- esnure we have a correct structure version!
|
||||||
|
_ASSERTE( uiFixedVersionSize == sizeof( VS_FIXEDFILEINFO ) );
|
||||||
|
|
||||||
|
//--- format the module name, version info & module path all nice and pretty
|
||||||
|
_stprintf( acBuff, _T( "%-15.15s: %3d.%02d.%02d.%04d %s\r\n" ),
|
||||||
|
s_aszModules_c[ i ],
|
||||||
|
HIWORD( pFixedVersionInfo->dwProductVersionMS ),
|
||||||
|
LOWORD( pFixedVersionInfo->dwProductVersionMS ),
|
||||||
|
HIWORD( pFixedVersionInfo->dwProductVersionLS ),
|
||||||
|
LOWORD( pFixedVersionInfo->dwProductVersionLS ),
|
||||||
|
acModulePath );
|
||||||
|
|
||||||
|
//--- clean-up
|
||||||
|
delete [] pcVersionInfo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//--- no version info, but the module itself, as well as it's path, are still interesting
|
||||||
|
// to know
|
||||||
|
_stprintf( acBuff, _T( "%-15.15s: <no version info> %s\r\n" ),
|
||||||
|
s_aszModules_c[ i ],
|
||||||
|
acModulePath );
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- accummulate all the info in a single buffer
|
||||||
|
if( ( _tcslen( acFinalBuff ) + _tcslen( acBuff ) ) < ( sizeof( acFinalBuff ) - 1 ) )
|
||||||
|
{
|
||||||
|
//--- plenty of room
|
||||||
|
_tcscat( acFinalBuff, acBuff );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//--- we just escaped a buffer overflow...
|
||||||
|
_tcscpy( acFinalBuff, _T( "<buffer too small>" ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- send the fully populated buffer to the edit control
|
||||||
|
HWND hEdit = ::GetDlgItem( hDlg, IDC_VERSION_EDIT );
|
||||||
|
::SetWindowText( hEdit, acFinalBuff );
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
//--- as the dlg resizes, have the edit control follow the client area's size
|
||||||
|
RECT rect;
|
||||||
|
::GetClientRect( hDlg, &rect );
|
||||||
|
HWND hEdit = ::GetDlgItem( hDlg, IDC_VERSION_EDIT );
|
||||||
|
::SetWindowPos( hEdit, NULL, rect.left, rect.top,
|
||||||
|
LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER | SWP_NOACTIVATE );
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
//--- kill the dialog when we get canceled by the user
|
||||||
|
if( IDCANCEL == LOWORD( wParam ) )
|
||||||
|
{
|
||||||
|
EndDialog( hDlg, LOWORD( wParam ));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- we didn't process this msg, let the default behavior prevail
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
} /* ComponentVersions */
|
23
mp/src/utils/sapi51/Samples/CPP/Common/sapisdkcommon.h
Normal file
23
mp/src/utils/sapi51/Samples/CPP/Common/sapisdkcommon.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* SapiSDKCommon.h
|
||||||
|
* This header is the main entry point for all the utilities &
|
||||||
|
* sub-features that are common the SAPI samples & tools.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//--- Includes --------------------------------------------------------------
|
||||||
|
|
||||||
|
//--- Forward and External Declarations -------------------------------------
|
||||||
|
|
||||||
|
//--- TypeDef and Enumeration Declarations ----------------------------------
|
||||||
|
|
||||||
|
//--- Constants -------------------------------------------------------------
|
||||||
|
|
||||||
|
//--- Class, Struct and Union Definitions -----------------------------------
|
||||||
|
|
||||||
|
//--- Function Declarations -------------------------------------------------
|
||||||
|
LRESULT CALLBACK ComponentVersionsDlgProc( HWND, UINT, WPARAM, LPARAM );
|
||||||
|
|
||||||
|
//--- Inline Function Definitions -------------------------------------------
|
17
mp/src/utils/sapi51/Samples/CPP/Common/sapisdkcommon.rc2
Normal file
17
mp/src/utils/sapi51/Samples/CPP/Common/sapisdkcommon.rc2
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* SapiSDKCommon.rc2
|
||||||
|
* This file contains the resource compiler directives for the dialogs
|
||||||
|
* exposed from the SAPI SDK common directory
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999 Microsoft Corporation All Rights Reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "SapiSDKCommonResources.h"
|
||||||
|
|
||||||
|
IDD_COMPONENT_VERSION_DLG DIALOG DISCARDABLE 0, 0, 354, 228
|
||||||
|
STYLE WS_POPUP | WS_CAPTION | WS_MAXIMIZEBOX | WS_SYSMENU | WS_THICKFRAME
|
||||||
|
CAPTION "Component Versions"
|
||||||
|
FONT 9, "Courier New"
|
||||||
|
BEGIN
|
||||||
|
EDITTEXT IDC_VERSION_EDIT,7,7,340,214,ES_MULTILINE | ES_READONLY | WS_VSCROLL |
|
||||||
|
WS_HSCROLL
|
||||||
|
END
|
@ -0,0 +1,2 @@
|
|||||||
|
#define IDC_VERSION_EDIT 10000
|
||||||
|
#define IDD_COMPONENT_VERSION_DLG 10001
|
705
mp/src/utils/sapi51/Samples/CPP/DictPad/candidatelist.cpp
Normal file
705
mp/src/utils/sapi51/Samples/CPP/DictPad/candidatelist.cpp
Normal file
@ -0,0 +1,705 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* candidatelist.cpp
|
||||||
|
* Implementation details for the CCandidateList object which is a
|
||||||
|
* class that manages the recognized alternatives for dictated
|
||||||
|
* text.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "candidatelist.h"
|
||||||
|
#include "dictpad.h"
|
||||||
|
|
||||||
|
// Multi-Language Header File
|
||||||
|
#include <mlang.h>
|
||||||
|
|
||||||
|
#define MAX_ALTS_DISPLAYED 10
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* CCandidateList::CCandidateList *
|
||||||
|
*--------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Constructor for the CCandidateList class.
|
||||||
|
* Modifies the RICHEDIT_CLASS of the main
|
||||||
|
* application window to use our callback function
|
||||||
|
* and registers that window class.
|
||||||
|
*******************************************************************************/
|
||||||
|
CCandidateList::CCandidateList( HWND hClient, CRecoEventMgr &rRecoMgr ) :
|
||||||
|
m_pwcParentClass( NULL ),
|
||||||
|
m_hMainClientWindow( hClient ),
|
||||||
|
m_hParent( NULL ),
|
||||||
|
m_hAltsList( NULL ),
|
||||||
|
// For now, set the langid to default.
|
||||||
|
// LangID can be set to something else
|
||||||
|
// later.
|
||||||
|
m_langid( ::GetUserDefaultLangID() ),
|
||||||
|
m_fMakeUIVisible( true ),
|
||||||
|
m_fPlaybackInProgress( false ),
|
||||||
|
m_pCurrentDictRun( NULL ),
|
||||||
|
m_cpTextSel( NULL ),
|
||||||
|
m_pRecoMgr( &rRecoMgr ),
|
||||||
|
m_hFont( NULL ),
|
||||||
|
m_ulNumAltsDisplayed( 0 )
|
||||||
|
{
|
||||||
|
m_hInst = (HINSTANCE) ::GetWindowLong( m_hMainClientWindow, GWL_HINSTANCE );
|
||||||
|
|
||||||
|
// Register a window class that is like the rich edit control class in every way
|
||||||
|
// except that it has space for an extra pointer and calls our wndproc
|
||||||
|
WNDCLASS wcModifiedRichEdit;
|
||||||
|
::GetClassInfo( m_hInst, RICHEDIT_CLASS, &wcModifiedRichEdit );
|
||||||
|
|
||||||
|
// Bump the space by the size of a pointer
|
||||||
|
m_cbOffset = wcModifiedRichEdit.cbWndExtra;
|
||||||
|
int cbExtraSpace = sizeof(CCandidateList *);
|
||||||
|
wcModifiedRichEdit.cbWndExtra += cbExtraSpace;
|
||||||
|
|
||||||
|
// Change the wndproc, storing the original wndproc
|
||||||
|
m_wpOrigWndProc = wcModifiedRichEdit.lpfnWndProc;
|
||||||
|
wcModifiedRichEdit.lpfnWndProc = CandidateUIProc;
|
||||||
|
|
||||||
|
wcModifiedRichEdit.lpszClassName = MODIFIED_RICHEDIT_NAME;
|
||||||
|
ATOM atomRet = ::RegisterClass( &wcModifiedRichEdit );
|
||||||
|
|
||||||
|
if ( atomRet )
|
||||||
|
{
|
||||||
|
m_pwcParentClass = new WNDCLASS;
|
||||||
|
*m_pwcParentClass = wcModifiedRichEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetFontSettings();
|
||||||
|
} /* CCandidateList::CCandidateList */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::~CCandidateList *
|
||||||
|
*---------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Destructor for the CCandidateListclass
|
||||||
|
*******************************************************************************/
|
||||||
|
CCandidateList::~CCandidateList()
|
||||||
|
{
|
||||||
|
if ( m_pwcParentClass )
|
||||||
|
{
|
||||||
|
delete m_pwcParentClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hFont)
|
||||||
|
{
|
||||||
|
DeleteObject(m_hFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
::DestroyWindow( m_hButton );
|
||||||
|
DoneWithAltsList();
|
||||||
|
} /* CCandidateList::~CCandidateList */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::GetFontSettings *
|
||||||
|
*---------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Gets the font settings for the candidate list UI
|
||||||
|
*******************************************************************************/
|
||||||
|
void CCandidateList::GetFontSettings()
|
||||||
|
{
|
||||||
|
int iHeight = 0; // Will cause CreateFont() to use default in case we
|
||||||
|
// don't get the height below
|
||||||
|
HDC hdc = GetDC(m_hMainClientWindow);
|
||||||
|
HFONT hfontNew = 0;
|
||||||
|
|
||||||
|
// Get the height of the text
|
||||||
|
if (hdc)
|
||||||
|
{
|
||||||
|
TEXTMETRIC tm;
|
||||||
|
|
||||||
|
if (GetTextMetrics(hdc, &tm))
|
||||||
|
{
|
||||||
|
iHeight = tm.tmHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseDC(m_hMainClientWindow, hdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick an appropriate font. On Windows 2000, let the system fontlink.
|
||||||
|
if (NT5orGreater())
|
||||||
|
{
|
||||||
|
hfontNew = CreateFont(iHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0,
|
||||||
|
DEFAULT_CHARSET,
|
||||||
|
OUT_DEFAULT_PRECIS,
|
||||||
|
CLIP_DEFAULT_PRECIS,
|
||||||
|
DEFAULT_QUALITY,
|
||||||
|
DEFAULT_PITCH,
|
||||||
|
TEXT("Microsoft Sans Serif"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LCID lcid = MAKELCID( m_langid, SORT_DEFAULT );
|
||||||
|
UINT uiCodePage = SpCodePageFromLcid( lcid );
|
||||||
|
|
||||||
|
CComPtr<IMultiLanguage> cpMultiLanguage;
|
||||||
|
MIMECPINFO MimeCpInfo;
|
||||||
|
|
||||||
|
if ( SUCCEEDED(cpMultiLanguage.CoCreateInstance(CLSID_CMultiLanguage))
|
||||||
|
&& SUCCEEDED(cpMultiLanguage->GetCodePageInfo(uiCodePage, &MimeCpInfo)))
|
||||||
|
{
|
||||||
|
USES_CONVERSION;
|
||||||
|
|
||||||
|
hfontNew = CreateFont(iHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0,
|
||||||
|
MimeCpInfo.bGDICharset,
|
||||||
|
OUT_DEFAULT_PRECIS,
|
||||||
|
CLIP_DEFAULT_PRECIS,
|
||||||
|
DEFAULT_QUALITY,
|
||||||
|
DEFAULT_PITCH,
|
||||||
|
W2T(MimeCpInfo.wszProportionalFont));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hfontNew)
|
||||||
|
{
|
||||||
|
if (m_hFont)
|
||||||
|
{
|
||||||
|
DeleteObject(m_hFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hFont = hfontNew;
|
||||||
|
}
|
||||||
|
} /* CCandidateList::GetFontSettings */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::SetParent *
|
||||||
|
*---------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called after the parent window is created.
|
||||||
|
* Sets the parent window member and creates a button for the
|
||||||
|
* alternates UI
|
||||||
|
*******************************************************************************/
|
||||||
|
void CCandidateList::SetParent( HWND hParent )
|
||||||
|
{
|
||||||
|
m_hParent = hParent;
|
||||||
|
m_hButton = ::CreateWindow( _T("BUTTON"),
|
||||||
|
_T(""),
|
||||||
|
WS_CHILD | BS_DEFPUSHBUTTON,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
BUTTON_WIDTH,
|
||||||
|
BUTTON_HEIGHT,
|
||||||
|
m_hParent,
|
||||||
|
NULL,
|
||||||
|
m_hInst,
|
||||||
|
NULL );
|
||||||
|
} /* CCandidateList::SetParent */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::SetLangID *
|
||||||
|
*---------------------------*
|
||||||
|
* Description:
|
||||||
|
* Sets the m_langid and calls GetFontSettings()
|
||||||
|
*******************************************************************************/
|
||||||
|
void CCandidateList::SetLangID( LANGID langid )
|
||||||
|
{
|
||||||
|
m_langid = langid;
|
||||||
|
GetFontSettings();
|
||||||
|
} /* CCandidateList::SetLangID */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::Update *
|
||||||
|
*------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called whenever an EN_SELCHANGE notification is received.
|
||||||
|
* Shows the alternates button if the entire selection is
|
||||||
|
* dictated text from the same phrase.
|
||||||
|
* Return:
|
||||||
|
* If the entire selection is within a single dictated text range, returns
|
||||||
|
* the handle to the button and shows the button.
|
||||||
|
* Otherwise returns NULL and hides the button.
|
||||||
|
********************************************************************************/
|
||||||
|
HWND CCandidateList::Update( CTextRunList *pTextRunList )
|
||||||
|
{
|
||||||
|
// Clicking off the alternates list should dismiss it
|
||||||
|
if ( m_hAltsList )
|
||||||
|
{
|
||||||
|
DoneWithAltsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pCurrentDictRun = NULL;
|
||||||
|
|
||||||
|
::ShowWindow( m_hButton, SW_HIDE );
|
||||||
|
::InvalidateRect( m_hParent, NULL, true );
|
||||||
|
|
||||||
|
if ( !m_fMakeUIVisible )
|
||||||
|
{
|
||||||
|
// The button should not be displayed
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !m_cpTextSel || !pTextRunList || !m_hParent )
|
||||||
|
{
|
||||||
|
// error
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lStart;
|
||||||
|
long lEnd;
|
||||||
|
HRESULT hr = m_cpTextSel->GetStart( &lStart );
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
hr = m_cpTextSel->GetEnd( &lEnd );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the alternates UI only if there is no reco computation
|
||||||
|
if ( SUCCEEDED( hr ) && m_pRecoMgr && !(m_pRecoMgr->IsProcessingPhrase()) )
|
||||||
|
{
|
||||||
|
PTEXTRUNNODE pNode = pTextRunList->Find( lStart );
|
||||||
|
if ( pNode && pNode->pTextRun->IsDict() &&
|
||||||
|
( lEnd <= pNode->pTextRun->GetEnd() ) )
|
||||||
|
{
|
||||||
|
// The selection is completely contained within this dictated run.
|
||||||
|
// The button should appear at the lower right-hand
|
||||||
|
// corner of the selected text
|
||||||
|
POINT pt;
|
||||||
|
hr = m_cpTextSel->GetPoint( tomEnd | TA_BASELINE | TA_LEFT,
|
||||||
|
&(pt.x), &(pt.y) );
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
// Move the button to the new location
|
||||||
|
::ScreenToClient( m_hParent, &pt );
|
||||||
|
::MoveWindow( m_hButton, pt.x, pt.y,
|
||||||
|
BUTTON_WIDTH, BUTTON_HEIGHT, true );
|
||||||
|
::ShowWindow( m_hButton, SW_SHOW );
|
||||||
|
|
||||||
|
// We know that this node contains a dictation run (see above)
|
||||||
|
m_pCurrentDictRun =
|
||||||
|
static_cast<CDictationRun *>(pNode->pTextRun);
|
||||||
|
|
||||||
|
return m_hButton;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, hide the window and return NULL
|
||||||
|
return NULL;
|
||||||
|
} /* CCandidateList::Update */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::ShowAlternates *
|
||||||
|
*--------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called whenever the alternates button is clicked.
|
||||||
|
* Hides the alternates button and displays the
|
||||||
|
* alternates dialog box.
|
||||||
|
* When the alternates dialog box is done, shows the button again.
|
||||||
|
********************************************************************************/
|
||||||
|
void CCandidateList::ShowAlternates()
|
||||||
|
{
|
||||||
|
_ASSERTE( m_pCurrentDictRun );
|
||||||
|
_ASSERTE( m_cpTextSel );
|
||||||
|
|
||||||
|
// Get the alternates. The text for the alternates
|
||||||
|
// will have been CoTaskMemAlloced
|
||||||
|
WCHAR *apszAltsText[ALT_REQUEST_COUNT];
|
||||||
|
bool apfFitsInRun[ ALT_REQUEST_COUNT ];
|
||||||
|
long lAltStart;
|
||||||
|
long lAltEnd;
|
||||||
|
ULONG cAltsReturned = 0;
|
||||||
|
HRESULT hr = m_pCurrentDictRun->GetAlternatesText(
|
||||||
|
m_cpTextSel, ALT_REQUEST_COUNT, &lAltStart, &lAltEnd,
|
||||||
|
apszAltsText, apfFitsInRun, &cAltsReturned );
|
||||||
|
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to make sure that at least one alternate is displayable
|
||||||
|
bool fDisplayableAlts = false;
|
||||||
|
for ( ULONG ulAlt = 0; !fDisplayableAlts && (ulAlt < cAltsReturned); ulAlt++ )
|
||||||
|
{
|
||||||
|
fDisplayableAlts = apfFitsInRun[ ulAlt ];
|
||||||
|
}
|
||||||
|
if ( !fDisplayableAlts )
|
||||||
|
{
|
||||||
|
// No alternates to display: Won't be doing anything here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide and disable the alternates button
|
||||||
|
_ASSERTE( m_hParent );
|
||||||
|
BOOL fVisible = ::ShowWindow( m_hButton, SW_HIDE );
|
||||||
|
_ASSERTE( fVisible );
|
||||||
|
::EnableWindow( m_hButton, false );
|
||||||
|
::InvalidateRect( m_hParent, NULL, true );
|
||||||
|
|
||||||
|
// Create a window for the alternates list.
|
||||||
|
// The alternates list should appear at the lower
|
||||||
|
// right-hand corner of the text selection
|
||||||
|
POINT pt;
|
||||||
|
m_cpTextSel->GetPoint( tomEnd | TA_BASELINE | TA_LEFT,
|
||||||
|
&(pt.x), &(pt.y) );
|
||||||
|
::ScreenToClient( m_hParent, &pt );
|
||||||
|
m_hAltsList = ::CreateWindow( _T("LISTBOX"),
|
||||||
|
_T(""),
|
||||||
|
WS_CHILD | WS_DLGFRAME | LBS_OWNERDRAWFIXED | LBS_NOTIFY | WS_VSCROLL,
|
||||||
|
pt.x, pt.y, // Dimensions will be determined by
|
||||||
|
// number and width of alternates
|
||||||
|
0, 0,
|
||||||
|
m_hParent,
|
||||||
|
(HMENU) IDC_LIST_ALTS,
|
||||||
|
m_hInst,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
// Get the font with which to draw the alternates (this is an
|
||||||
|
// owner-drawn listbox)
|
||||||
|
HDC hdc = ::GetDC( m_hAltsList );
|
||||||
|
HGDIOBJ hfontOld = m_hFont ? SelectObject(hdc, m_hFont) : 0;
|
||||||
|
|
||||||
|
// Populate the alternates list.
|
||||||
|
ULONG ulAltIndex;
|
||||||
|
ULONG ulNumAltsDisplayed = 0;
|
||||||
|
WCHAR **ppszCoMemText;
|
||||||
|
SIZE size;
|
||||||
|
int cxMaxWidth = 0;
|
||||||
|
for ( ulAltIndex = 0, ppszCoMemText = apszAltsText;
|
||||||
|
ulAltIndex < cAltsReturned;
|
||||||
|
ulAltIndex++, ppszCoMemText++ )
|
||||||
|
{
|
||||||
|
if ( !apfFitsInRun[ ulAltIndex ] )
|
||||||
|
{
|
||||||
|
// This alt will not be displayed, since the alt covers elements
|
||||||
|
// not in this run
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of which alternate is going into location
|
||||||
|
// cAltsListed in the alternates list
|
||||||
|
m_aulAltIndices[ ulNumAltsDisplayed ] = ulAltIndex;
|
||||||
|
|
||||||
|
// Keep track of the widest alt so far
|
||||||
|
_ASSERTE( *ppszCoMemText );
|
||||||
|
::GetTextExtentPointW(
|
||||||
|
hdc, *ppszCoMemText, wcslen( *ppszCoMemText ), &size );
|
||||||
|
cxMaxWidth = max( cxMaxWidth, size.cx );
|
||||||
|
|
||||||
|
// Owner-drawn list box, so the string is stored as item data (as a WCHAR *)
|
||||||
|
WCHAR *pwszListItem = wcsdup( *ppszCoMemText );
|
||||||
|
::SendMessage( m_hAltsList, LB_INSERTSTRING, ulNumAltsDisplayed, (LPARAM) pwszListItem );
|
||||||
|
|
||||||
|
ulNumAltsDisplayed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of how many alternates there are
|
||||||
|
m_ulNumAltsDisplayed = ulNumAltsDisplayed;
|
||||||
|
|
||||||
|
// Get the old font back
|
||||||
|
hfontOld ? SelectObject(hdc, hfontOld) : NULL;
|
||||||
|
::ReleaseDC( m_hAltsList, hdc );
|
||||||
|
|
||||||
|
// Bump up the maximum width by the list box border width and the
|
||||||
|
// vertical scroll bar width if necessary
|
||||||
|
cxMaxWidth += 2 * GetSystemMetrics( SM_CXDLGFRAME );
|
||||||
|
if (ulNumAltsDisplayed > MAX_ALTS_DISPLAYED)
|
||||||
|
{
|
||||||
|
cxMaxWidth += GetSystemMetrics( SM_CXVSCROLL );
|
||||||
|
}
|
||||||
|
|
||||||
|
// The alternates text was CoTaskMemAlloced, so we must free
|
||||||
|
// it now
|
||||||
|
ULONG ul;
|
||||||
|
for ( ul = 0, ppszCoMemText = apszAltsText;
|
||||||
|
ul < cAltsReturned;
|
||||||
|
ul++, ppszCoMemText++ )
|
||||||
|
{
|
||||||
|
if ( *ppszCoMemText )
|
||||||
|
{
|
||||||
|
::CoTaskMemFree( *ppszCoMemText );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize the window to the correct width
|
||||||
|
// The alternates list should always go inside the parent window,
|
||||||
|
// so if the list is too wide, move it to the left.
|
||||||
|
RECT rectButton;
|
||||||
|
RECT rectParent;
|
||||||
|
POINT ptTopLeft;
|
||||||
|
::GetWindowRect( m_hButton, &rectButton );
|
||||||
|
::GetWindowRect( m_hParent, &rectParent );
|
||||||
|
int cyItemHeight = ::SendMessage( m_hAltsList, LB_GETITEMHEIGHT, 0, 0 );
|
||||||
|
int cyHeight = __min(((int) ulNumAltsDisplayed + 1) * cyItemHeight,
|
||||||
|
(MAX_ALTS_DISPLAYED + 1) * cyItemHeight);
|
||||||
|
ptTopLeft.x = __min( rectButton.left, rectParent.right - cxMaxWidth );
|
||||||
|
ptTopLeft.y = rectButton.top;
|
||||||
|
::ScreenToClient( m_hParent, &ptTopLeft );
|
||||||
|
::MoveWindow( m_hAltsList,
|
||||||
|
ptTopLeft.x,
|
||||||
|
ptTopLeft.y,
|
||||||
|
cxMaxWidth,
|
||||||
|
cyHeight,
|
||||||
|
true );
|
||||||
|
|
||||||
|
|
||||||
|
// Display the alternates list
|
||||||
|
::ShowWindow( m_hAltsList, SW_SHOW );
|
||||||
|
|
||||||
|
// Highlight the text for the first alternate displayed
|
||||||
|
MakeTextSelReflectAlt(0);
|
||||||
|
|
||||||
|
::SetFocus( m_hAltsList );
|
||||||
|
} /* CCandidateList::ShowAlternates */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::ShowButton *
|
||||||
|
*----------------------------*
|
||||||
|
* Description:
|
||||||
|
* Shows/hides the alternates button.
|
||||||
|
********************************************************************************/
|
||||||
|
void CCandidateList::ShowButton( bool bShow )
|
||||||
|
{
|
||||||
|
::ShowWindow( m_hButton, bShow ? SW_SHOW : SW_HIDE );
|
||||||
|
::EnableWindow( m_hButton, bShow );
|
||||||
|
::InvalidateRect( m_hParent, NULL, true );
|
||||||
|
m_fMakeUIVisible = bShow;
|
||||||
|
} /* CCandidateList::ShowButton */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::MakeTextSelReflectAlt *
|
||||||
|
*---------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called when an item in the alternates list is selected.
|
||||||
|
* Adjusts the text selection in order to jive with whichever
|
||||||
|
* elements that alternate replaces
|
||||||
|
********************************************************************************/
|
||||||
|
void CCandidateList::MakeTextSelReflectAlt( ULONG ulAltIndexInList )
|
||||||
|
{
|
||||||
|
_ASSERTE( m_pCurrentDictRun );
|
||||||
|
_ASSERTE( m_cpTextSel );
|
||||||
|
_ASSERTE( ulAltIndexInList < m_ulNumAltsDisplayed );
|
||||||
|
|
||||||
|
long lSelStart;
|
||||||
|
long lSelEnd;
|
||||||
|
|
||||||
|
HRESULT hr = m_pCurrentDictRun->GetAltEndpoints(
|
||||||
|
m_aulAltIndices[ ulAltIndexInList ], &lSelStart, &lSelEnd );
|
||||||
|
|
||||||
|
if ( SUCCEEDED(hr) )
|
||||||
|
{
|
||||||
|
// The WM_STOPUPDATE message tells Dictpad that there is no
|
||||||
|
// new text, so it does not need to process this selection change
|
||||||
|
::SendMessage( m_hMainClientWindow, WM_STOPUPDATE, 0, 0 );
|
||||||
|
m_cpTextSel->SetStart( lSelStart );
|
||||||
|
m_cpTextSel->SetEnd( lSelEnd );
|
||||||
|
::SendMessage( m_hMainClientWindow, WM_STARTUPDATE, 0, 0 );
|
||||||
|
}
|
||||||
|
} /* CCandidateList::MakeTextSelReflectAlt */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::AlternateChosen *
|
||||||
|
*---------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called when the user selects an alternate from the alternates UI.
|
||||||
|
* Notifies the appropriate CDictationRun that the alt has been
|
||||||
|
* chosen and changes the text.
|
||||||
|
* Dismisses the alternates list, since choosing an alternate means
|
||||||
|
* the user is done with the alternates list.
|
||||||
|
********************************************************************************/
|
||||||
|
void CCandidateList::AlternateChosen( ULONG ulChosenAltInList )
|
||||||
|
{
|
||||||
|
_ASSERTE( m_hAltsList );
|
||||||
|
_ASSERTE( m_pCurrentDictRun );
|
||||||
|
_ASSERTE( m_cpTextSel );
|
||||||
|
_ASSERTE( ulChosenAltInList < m_ulNumAltsDisplayed );
|
||||||
|
|
||||||
|
::SendMessage( m_hMainClientWindow, WM_STOPUPDATE, 0, 0 );
|
||||||
|
HRESULT hr = m_pCurrentDictRun->ChooseAlternate(
|
||||||
|
m_aulAltIndices[ ulChosenAltInList ] );
|
||||||
|
::SendMessage( m_hMainClientWindow, WM_STARTUPDATE, 0, 0 );
|
||||||
|
|
||||||
|
// The main window should update the alternates button
|
||||||
|
::SendMessage( m_hMainClientWindow, WM_UPDATEALTSBUTTON, 0, 0 );
|
||||||
|
|
||||||
|
DoneWithAltsList();
|
||||||
|
} /* CCandidateList::AlternateChosen */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CCandidateList::DoneWithAltsList *
|
||||||
|
*----------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called when the alternates list no longer need be displayed.
|
||||||
|
* Either the user has chosen an alternate or the user has clicked
|
||||||
|
* off the list to dismiss it.
|
||||||
|
********************************************************************************/
|
||||||
|
void CCandidateList::DoneWithAltsList()
|
||||||
|
{
|
||||||
|
if ( !m_hAltsList )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cItems = ::SendMessage( m_hAltsList, LB_GETCOUNT, 0, 0 );
|
||||||
|
for ( int i = 0; i < cItems; i++ )
|
||||||
|
{
|
||||||
|
// Free the memory used for the strings in the list box
|
||||||
|
WCHAR *pwszListItem = (WCHAR *) ::SendMessage(
|
||||||
|
m_hAltsList, LB_GETITEMDATA, i, 0 );
|
||||||
|
if ( pwszListItem )
|
||||||
|
{
|
||||||
|
free( pwszListItem );
|
||||||
|
::SendMessage( m_hAltsList, LB_SETITEMDATA, i, NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ulNumAltsDisplayed = 0;
|
||||||
|
|
||||||
|
::DestroyWindow( m_hAltsList );
|
||||||
|
m_hAltsList = 0;
|
||||||
|
m_pCurrentDictRun = NULL;
|
||||||
|
|
||||||
|
// Bring the button back
|
||||||
|
::EnableWindow( m_hButton, true );
|
||||||
|
} /* CCandidateList::DoneWithAltsList */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CandidateUIProc() *
|
||||||
|
*-------------------*
|
||||||
|
* Description:
|
||||||
|
* Subclassing procedure for the richedit control so that it can process
|
||||||
|
* messages from the candidate list UI.
|
||||||
|
*******************************************************************************/
|
||||||
|
LRESULT APIENTRY CandidateUIProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
|
||||||
|
{
|
||||||
|
static int cbOffset = 0; // Where the data to be used by this
|
||||||
|
// wndproc starts
|
||||||
|
// The window long points to the associated instance of the candidate list UI
|
||||||
|
CCandidateList *pCandidateList =
|
||||||
|
( CCandidateList * ) ::GetWindowLong( hWnd, cbOffset );
|
||||||
|
|
||||||
|
switch( message )
|
||||||
|
{
|
||||||
|
case WM_NCCREATE:
|
||||||
|
{
|
||||||
|
// lParam points to a CREATESTRUCT with the CCandidateList * object
|
||||||
|
// as its lpCreateParams
|
||||||
|
pCandidateList = (CCandidateList *)
|
||||||
|
((LPCREATESTRUCT) lParam)->lpCreateParams;
|
||||||
|
|
||||||
|
// Get the class info and find the offset that will give us
|
||||||
|
// the very end of the extra space
|
||||||
|
WNDCLASS wc;
|
||||||
|
TCHAR pszClassName[ MAX_CLASS_NAME ];
|
||||||
|
::GetClassName( hWnd, pszClassName, MAX_CLASS_NAME );
|
||||||
|
::GetClassInfo( (HINSTANCE) ::GetWindowLong( hWnd, GWL_HINSTANCE ),
|
||||||
|
pszClassName, &wc );
|
||||||
|
_ASSERTE( wc.cbWndExtra >= sizeof( CCandidateList *) );
|
||||||
|
if ( wc.cbWndExtra < sizeof( CCandidateList * ) )
|
||||||
|
{
|
||||||
|
// No space for the CCandidateList * in the window long
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cbOffset = wc.cbWndExtra - sizeof( CCandidateList *);
|
||||||
|
|
||||||
|
// Set the window long
|
||||||
|
::SetWindowLong( hWnd, cbOffset, (long) pCandidateList );
|
||||||
|
|
||||||
|
// Tell the candidate list about the parent window
|
||||||
|
pCandidateList->SetParent( hWnd );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_CHAR:
|
||||||
|
// Ignore keystrokes as a recognition is being processed
|
||||||
|
if ( pCandidateList->m_pRecoMgr->IsProcessingPhrase()
|
||||||
|
|| ( pCandidateList->IsPlaybackInProgress() && ( VK_ESCAPE != wParam )) )
|
||||||
|
{
|
||||||
|
// Dropping these messages
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_IME_STARTCOMPOSITION:
|
||||||
|
if ( pCandidateList->m_pRecoMgr->IsProcessingPhrase()
|
||||||
|
|| ( pCandidateList->IsPlaybackInProgress() && ( VK_ESCAPE != wParam )) )
|
||||||
|
{
|
||||||
|
HIMC himc = ::ImmGetContext( hWnd );
|
||||||
|
::ImmNotifyIME( himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0 );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch ( HIWORD( wParam ) )
|
||||||
|
{
|
||||||
|
case BN_CLICKED:
|
||||||
|
// Clicking on the alternates button
|
||||||
|
pCandidateList->ShowAlternates();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LBN_SELCHANGE:
|
||||||
|
// Selecting a different alternate in the alternates list
|
||||||
|
pCandidateList->MakeTextSelReflectAlt(
|
||||||
|
::SendMessage( pCandidateList->m_hAltsList, LB_GETCURSEL, 0, 0 ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LBN_DBLCLK:
|
||||||
|
// Choosing an alternate
|
||||||
|
pCandidateList->AlternateChosen(
|
||||||
|
::SendMessage( pCandidateList->m_hAltsList, LB_GETCURSEL, 0, 0 ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LBN_SETFOCUS:
|
||||||
|
// When the alternates list first appears, we give it the input
|
||||||
|
// focus. The first alternate should start out selected
|
||||||
|
::SendMessage( pCandidateList->m_hAltsList, LB_SETCURSEL, 0, 0 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DRAWITEM:
|
||||||
|
// Since we have an owner-draw list box we need to process this
|
||||||
|
// message
|
||||||
|
if (wParam == IDC_LIST_ALTS)
|
||||||
|
{
|
||||||
|
LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT)lParam;
|
||||||
|
|
||||||
|
HGDIOBJ hfontOld = pCandidateList->m_hFont ?
|
||||||
|
SelectObject( pdis->hDC, pCandidateList->m_hFont ) : NULL;
|
||||||
|
UINT oldTextAlign = GetTextAlign(pdis->hDC);
|
||||||
|
|
||||||
|
UINT options = ETO_OPAQUE | ETO_CLIPPED;
|
||||||
|
|
||||||
|
// Strings are stored as item data
|
||||||
|
HWND hwndList = pCandidateList->m_hAltsList;
|
||||||
|
WCHAR *pwszItemText = (WCHAR *) ::SendMessage( hwndList,
|
||||||
|
LB_GETITEMDATA, pdis->itemID, 0 );
|
||||||
|
|
||||||
|
int cStringLen = wcslen( pwszItemText );
|
||||||
|
|
||||||
|
SetTextAlign(pdis->hDC, TA_UPDATECP);
|
||||||
|
MoveToEx(pdis->hDC, pdis->rcItem.left, pdis->rcItem.top, NULL);
|
||||||
|
ExtTextOutW(pdis->hDC,
|
||||||
|
pdis->rcItem.left, pdis->rcItem.top,
|
||||||
|
options,
|
||||||
|
&pdis->rcItem,
|
||||||
|
pwszItemText,
|
||||||
|
cStringLen,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
|
||||||
|
SetTextAlign(pdis->hDC, oldTextAlign);
|
||||||
|
|
||||||
|
if (hfontOld)
|
||||||
|
{
|
||||||
|
SelectObject(pdis->hDC, hfontOld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the original WndProc
|
||||||
|
return ::CallWindowProc( pCandidateList->m_wpOrigWndProc,
|
||||||
|
hWnd, message, wParam, lParam );
|
||||||
|
} /* CandidateUIProc */
|
||||||
|
|
108
mp/src/utils/sapi51/Samples/CPP/DictPad/candidatelist.h
Normal file
108
mp/src/utils/sapi51/Samples/CPP/DictPad/candidatelist.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* candidatelist.h
|
||||||
|
* This module contains the definition support for CCandidateList,
|
||||||
|
* the candidate list UI for Dictpad
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __CANDIDATELIST_H
|
||||||
|
#define __CANDIDATELIST_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <richedit.h>
|
||||||
|
#include <richole.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include "sapi.h"
|
||||||
|
#include "TextRunList.h"
|
||||||
|
#include "recomgr.h"
|
||||||
|
|
||||||
|
#define BUTTON_WIDTH 16
|
||||||
|
#define BUTTON_HEIGHT 16
|
||||||
|
#define MODIFIED_RICHEDIT_NAME _T("modified_richedit")
|
||||||
|
#define MAX_CLASS_NAME 50
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CCandidateList
|
||||||
|
* Handles the UI for the alternate list
|
||||||
|
*****************************************************************************/
|
||||||
|
class CCandidateList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCandidateList( HWND hClient, CRecoEventMgr &rRecoMgr );
|
||||||
|
~CCandidateList();
|
||||||
|
|
||||||
|
void GetFontSettings();
|
||||||
|
|
||||||
|
const WNDCLASS *GetParentClass()
|
||||||
|
{ return m_pwcParentClass; }
|
||||||
|
void SetParent( HWND hParent );
|
||||||
|
void SetTextSel( ITextSelection *pTextSel )
|
||||||
|
{ m_cpTextSel = pTextSel; }
|
||||||
|
void SetLangID( LANGID langid );
|
||||||
|
|
||||||
|
HWND Update( CTextRunList *pTextRunList );
|
||||||
|
void ShowButton( bool fShow );
|
||||||
|
|
||||||
|
void StartPlayback() {m_fPlaybackInProgress = true;};
|
||||||
|
void EndPlayback() {m_fPlaybackInProgress = false;};
|
||||||
|
bool IsPlaybackInProgress() { return m_fPlaybackInProgress; };
|
||||||
|
|
||||||
|
friend LRESULT APIENTRY CandidateUIProc(
|
||||||
|
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
|
||||||
|
|
||||||
|
bool FHasAlternates() { return (m_pCurrentDictRun != NULL) && (m_cpTextSel != NULL); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ShowAlternates();
|
||||||
|
void MakeTextSelReflectAlt( ULONG ulAltIndexInList );
|
||||||
|
void AlternateChosen( ULONG ulChosenAltInList );
|
||||||
|
void DoneWithAltsList();
|
||||||
|
|
||||||
|
// Data members
|
||||||
|
|
||||||
|
WNDCLASS *m_pwcParentClass; // The window class registered by the
|
||||||
|
// call to the constructor for a candidate list
|
||||||
|
// (a modified RichEdit control).
|
||||||
|
// The parent window will belong to this window class.
|
||||||
|
HINSTANCE m_hInst;
|
||||||
|
HWND m_hMainClientWindow;// Main application window
|
||||||
|
HWND m_hParent; // Parent window of the UI (richedit control)
|
||||||
|
int m_cbOffset; // Offset of the extra space in the parent window
|
||||||
|
WNDPROC m_wpOrigWndProc; // The wndproc of the parent window that will be
|
||||||
|
// subclassed
|
||||||
|
HWND m_hButton; // The button that triggers the alternates UI
|
||||||
|
HWND m_hAltsList; // Handle to the alternates list
|
||||||
|
LANGID m_langid; // Language of dictation
|
||||||
|
HFONT m_hFont; // Font for the owner-drawn alternates listbox
|
||||||
|
bool m_fMakeUIVisible; // If false, button and list not shown
|
||||||
|
bool m_fPlaybackInProgress;
|
||||||
|
// If true, richedit window needs to ignore keystrokes
|
||||||
|
|
||||||
|
CDictationRun *m_pCurrentDictRun;
|
||||||
|
// The last dictation run that the alternates button
|
||||||
|
// corresponded to
|
||||||
|
|
||||||
|
CComPtr<ITextSelection> m_cpTextSel;
|
||||||
|
CRecoEventMgr *m_pRecoMgr;
|
||||||
|
ULONG m_aulAltIndices[ ALT_REQUEST_COUNT ];
|
||||||
|
ULONG m_ulNumAltsDisplayed;
|
||||||
|
// A map from indices in the list to alternate indices
|
||||||
|
};
|
||||||
|
|
||||||
|
// Subclassing wndproc for the richedit control (parent window of the candidate UI
|
||||||
|
LRESULT APIENTRY CandidateUIProc(
|
||||||
|
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
|
||||||
|
|
||||||
|
// Helper function for locale and font settings
|
||||||
|
inline BOOL NT5orGreater()
|
||||||
|
{
|
||||||
|
DWORD dwVersion = GetVersion();
|
||||||
|
|
||||||
|
return !(dwVersion & 0x80000000) && LOBYTE(LOWORD(dwVersion)) >= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __CANDIDATELIST_H
|
255
mp/src/utils/sapi51/Samples/CPP/DictPad/chs_cmdmode.xml
Normal file
255
mp/src/utils/sapi51/Samples/CPP/DictPad/chs_cmdmode.xml
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<GRAMMAR LANGID="804">
|
||||||
|
<DEFINE>
|
||||||
|
<ID NAME="PID_CmdMenu" VAL="1"/>
|
||||||
|
<ID NAME="PID_CmdSysMenu" VAL="2"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuFile" VAL="100"/>
|
||||||
|
<ID NAME="PID_CmdNew" VAL="101"/>
|
||||||
|
<ID NAME="PID_CmdOpen" VAL="102"/>
|
||||||
|
<ID NAME="PID_CmdSave" VAL="103"/>
|
||||||
|
<ID NAME="PID_CmdSaveAs" VAL="104"/>
|
||||||
|
<ID NAME="PID_CmdExit" VAL="105"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuEdit" VAL="200"/>
|
||||||
|
<ID NAME="PID_CmdCut" VAL="201"/>
|
||||||
|
<ID NAME="PID_CmdCopy" VAL="202"/>
|
||||||
|
<ID NAME="PID_CmdPaste" VAL="203"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuVoice" VAL="300"/>
|
||||||
|
<ID NAME="PID_CmdDictationMode" VAL="301"/>
|
||||||
|
<ID NAME="PID_CmdCommandMode" VAL="302"/>
|
||||||
|
<ID NAME="PID_CmdMicrophone" VAL="303"/>
|
||||||
|
<ID NAME="PID_CmdPlayback" VAL="304"/>
|
||||||
|
<ID NAME="PID_CmdAddDeleteWords" VAL="305"/>
|
||||||
|
<ID NAME="PID_CmdSelectWholeWords" VAL="306"/>
|
||||||
|
<ID NAME="PID_CmdSharedRecoEngine" VAL="307"/>
|
||||||
|
<ID NAME="PID_CmdVoiceTraining" VAL="310"/>
|
||||||
|
<ID NAME="PID_CmdMicrophoneSetup" VAL="311"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuHelp" VAL="500"/>
|
||||||
|
<ID NAME="PID_CmdAbout" VAL="501"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdEscape" VAL="903"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNavigationVertical" VAL="1000"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdDirection" VAL="1100"/>
|
||||||
|
<ID NAME="PID_CmdUp" VAL="1001"/>
|
||||||
|
<ID NAME="PID_CmdDown" VAL="1002"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdUnits" VAL="1200"/>
|
||||||
|
<ID NAME="PID_CmdPage" VAL="1201"/>
|
||||||
|
<ID NAME="PID_CmdLine" VAL="1202"/>
|
||||||
|
<ID NAME="PID_CmdParagraph" VAL="1203"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNumber" VAL="1300"/>
|
||||||
|
<ID NAME="PID_Ones" VAL="1301"/>
|
||||||
|
<ID NAME="PID_Tens" VAL="1302"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNavigationOther" VAL="2000"/>
|
||||||
|
<ID NAME="PID_CmdScrollHome" VAL="2001"/>
|
||||||
|
<ID NAME="PID_CmdScrollEnd" VAL="2002"/>
|
||||||
|
<ID NAME="PID_CmdLineEnd" VAL="2003"/>
|
||||||
|
<ID NAME="PID_CmdLineHome" VAL="2004"/>
|
||||||
|
<ID NAME="PID_CmdCharacterLeft" VAL="2005"/>
|
||||||
|
<ID NAME="PID_CmdCharacterRight" VAL="2006"/>
|
||||||
|
<ID NAME="PID_CmdWordLeft" VAL="2007"/>
|
||||||
|
<ID NAME="PID_CmdWordRight" VAL="2008"/>
|
||||||
|
|
||||||
|
</DEFINE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNavigationVertical" ID="PID_CmdNavigationVertical" TOPLEVEL="ACTIVE" EXPORT="1">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<L>
|
||||||
|
<P>scroll</P>
|
||||||
|
<P>move</P>
|
||||||
|
</L>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<RULEREF NAME="PID_CmdNumber" PROPNAME="PID_CmdNumber" PROPID="PID_CmdNumber"/>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdUnits" PROPID="PID_CmdUnits">
|
||||||
|
<P VAL="PID_CmdPage">page</P>
|
||||||
|
<P VAL="PID_CmdPage">pages</P>
|
||||||
|
<P VAL="PID_CmdLine">line</P>
|
||||||
|
<P VAL="PID_CmdLine">lines</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraph</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraphs</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
</P>
|
||||||
|
|
||||||
|
<P>
|
||||||
|
<L PROPNAME="PID_CmdUnits" PROPID="PID_CmdUnits">
|
||||||
|
<P VAL="PID_CmdPage">page</P>
|
||||||
|
<P VAL="PID_CmdLine">line</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraph</P>
|
||||||
|
</L>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNumber" ID="PID_CmdNumber" TOPLEVEL="INACTIVE" EXPORT="1">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="onesfrag"/>
|
||||||
|
</P>
|
||||||
|
<P>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="tens"/>
|
||||||
|
</P>
|
||||||
|
<O>
|
||||||
|
<RULEREF NAME="ones"/>
|
||||||
|
</O>
|
||||||
|
</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNavigationOther" ID="PID_CmdNavigationOther" TOPLEVEL="ACTIVE" EXPORT="1">
|
||||||
|
<L PROPNAME="PID_CmdNavigationOther" PROPID="PID_CmdNavigationOther">
|
||||||
|
<P VAL="PID_CmdScrollHome">go home</P>
|
||||||
|
<P VAL="PID_CmdScrollHome">scroll home</P>
|
||||||
|
<P VAL="PID_CmdScrollEnd">go end</P>
|
||||||
|
<P VAL="PID_CmdScrollEnd">scroll end</P>
|
||||||
|
<P VAL="PID_CmdCharacterLeft">?move left</P>
|
||||||
|
<P VAL="PID_CmdCharacterLeft">scroll left</P>
|
||||||
|
<P VAL="PID_CmdCharacterRight">?move right</P>
|
||||||
|
<P VAL="PID_CmdCharacterRight">scroll right</P>
|
||||||
|
<P VAL="PID_CmdWordLeft">word left</P>
|
||||||
|
<P VAL="PID_CmdWordRight">word right</P>
|
||||||
|
<P VAL="PID_CmdLineEnd">?line end</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line home</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line start</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line beginning</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdMenu" ID="PID_CmdMenu" TOPLEVEL="ACTIVE">
|
||||||
|
<L PROPNAME="PID_CmdMenu" PROPID="PID_CmdMenu">
|
||||||
|
<P VAL="PID_CmdMenuFile">file</P>
|
||||||
|
<P VAL="PID_CmdNew">new</P>
|
||||||
|
<P VAL="PID_CmdOpen">open</P>
|
||||||
|
<P VAL="PID_CmdSave">save</P>
|
||||||
|
<P VAL="PID_CmdSaveAs">save as</P>
|
||||||
|
<P VAL="PID_CmdExit">exit</P>
|
||||||
|
<P VAL="PID_CmdMenuEdit">edit</P>
|
||||||
|
<P VAL="PID_CmdCut">cut</P>
|
||||||
|
<P VAL="PID_CmdCopy">copy</P>
|
||||||
|
<P VAL="PID_CmdPaste">paste</P>
|
||||||
|
<P VAL="PID_CmdMenuVoice">voice</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">listen for dictation</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">?start dictation</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">start dictating</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">end ?of command mode</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">listen for command</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">listen for commands</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">stop dictation</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">end ?of dictation</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">stop dictating</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">?turn microphone off</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">?turn mike off</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">close microphone</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">microphone on</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">grammars active</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">grammars inactive</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">activate grammars</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">deactivate grammars</P>
|
||||||
|
<P VAL="PID_CmdPlayback">play</P>
|
||||||
|
<P VAL="PID_CmdPlayback">play back</P>
|
||||||
|
<P VAL="PID_CmdAddDeleteWords">add ?and delete word</P>
|
||||||
|
<P VAL="PID_CmdSelectWholeWords">select whole word</P>
|
||||||
|
<P VAL="PID_CmdSelectWholeWords">select whole words</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared engine</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared recognition engine</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared reco engine</P>
|
||||||
|
<P VAL="PID_CmdVoiceTraining">?voice training</P>
|
||||||
|
<P VAL="PID_CmdMicrophoneSetup">microphone setup</P>
|
||||||
|
<P VAL="PID_CmdMenuHelp">help</P>
|
||||||
|
<P VAL="PID_CmdAbout">about</P>
|
||||||
|
<P VAL="PID_CmdEscape">cancel</P>
|
||||||
|
<P VAL="PID_CmdEscape">escape</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<!-- Internal number rules -->
|
||||||
|
<RULE NAME="tens">
|
||||||
|
<L PROPNAME="PID_Tens" PROPID="PID_Tens">
|
||||||
|
<P VAL="20">twenty</P>
|
||||||
|
<P VAL="30">thirty</P>
|
||||||
|
<P VAL="40">forty</P>
|
||||||
|
<P VAL="50">fifty</P>
|
||||||
|
<P VAL="60">sixty</P>
|
||||||
|
<P VAL="70">seventy</P>
|
||||||
|
<P VAL="80">eighty</P>
|
||||||
|
<P VAL="90">ninety</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="ones">
|
||||||
|
<L PROPNAME="PID_Ones" PROPID="PID_Ones">
|
||||||
|
<P VAL="1">one</P>
|
||||||
|
<P VAL="2">two</P>
|
||||||
|
<P VAL="3">three</P>
|
||||||
|
<P VAL="4">four</P>
|
||||||
|
<P VAL="5">five</P>
|
||||||
|
<P VAL="6">six</P>
|
||||||
|
<P VAL="7">seven</P>
|
||||||
|
<P VAL="8">eight</P>
|
||||||
|
<P VAL="9">nine</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="onesfrag">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="ones"/>
|
||||||
|
</P>
|
||||||
|
<L PROPNAME="PID_Ones" PROPID="PID_Ones">
|
||||||
|
<P VAL="0">zero</P>
|
||||||
|
<P VAL="10">ten</P>
|
||||||
|
<P VAL="11">eleven</P>
|
||||||
|
<P VAL="12">twelve</P>
|
||||||
|
<P VAL="13">thirteen</P>
|
||||||
|
<P VAL="14">fourteen</P>
|
||||||
|
<P VAL="15">fifteen</P>
|
||||||
|
<P VAL="16">sixteen</P>
|
||||||
|
<P VAL="17">seventeen</P>
|
||||||
|
<P VAL="18">eighteen</P>
|
||||||
|
<P VAL="19">nineteen</P>
|
||||||
|
</L>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
</GRAMMAR>
|
15
mp/src/utils/sapi51/Samples/CPP/DictPad/chs_dictmode.xml
Normal file
15
mp/src/utils/sapi51/Samples/CPP/DictPad/chs_dictmode.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<GRAMMAR LANGID="804">
|
||||||
|
<DEFINE>
|
||||||
|
<ID NAME="PID_DictMode" VAL="1"/>
|
||||||
|
<ID NAME="PID_DictCommand" VAL="901"/>
|
||||||
|
|
||||||
|
</DEFINE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_DictMode" ID="PID_DictMode" TOPLEVEL="ACTIVE">
|
||||||
|
<L PROPNAME="PID_DictMode" PROPID="PID_DictMode">
|
||||||
|
<P VAL="PID_DictCommand">command</P>
|
||||||
|
<P VAL="PID_DictCommand">computer</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
</GRAMMAR>
|
137
mp/src/utils/sapi51/Samples/CPP/DictPad/chs_dictpad.rc
Normal file
137
mp/src/utils/sapi51/Samples/CPP/DictPad/chs_dictpad.rc
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Menu
|
||||||
|
//
|
||||||
|
|
||||||
|
IDC_DICTPAD MENU DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
POPUP "&File"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "&New\tCtrl+N", ID_FILE_NEW
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
|
||||||
|
MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
|
||||||
|
MENUITEM "Save &As...", ID_FILE_SAVEAS
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "E&xit\tCtrl+X", IDM_EXIT
|
||||||
|
END
|
||||||
|
POPUP "&Edit"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
|
||||||
|
MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
|
||||||
|
MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
|
||||||
|
END
|
||||||
|
POPUP "&Voice"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Listen for &Dictation", IDM_DICTATION_MODE, CHECKED
|
||||||
|
MENUITEM "Listen for &Commands", IDM_COMMAND_MODE
|
||||||
|
MENUITEM "&Grammars active\tCtrl+M", IDM_MIC_TOGGLE
|
||||||
|
MENUITEM "Play&back\tCtrl+P", IDM_PLAY
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Add/Delete Word(s)...", IDM_ADDREMOVEWORDS
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "Select &Whole Words", IDM_WHOLE_WORDS, CHECKED
|
||||||
|
MENUITEM "S&hared recognition engine", IDM_SHAREDENGINE
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Voice Training...", IDM_VOICE_TRAINING
|
||||||
|
MENUITEM "Micro&phone Setup...", IDM_MICROPHONE_SETUP
|
||||||
|
END
|
||||||
|
POPUP "&Help"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "&About ...", IDM_ABOUT
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Accelerator
|
||||||
|
//
|
||||||
|
|
||||||
|
IDC_DICTPAD ACCELERATORS MOVEABLE PURE
|
||||||
|
BEGIN
|
||||||
|
"/", IDM_ABOUT, ASCII, ALT, NOINVERT
|
||||||
|
"?", IDM_ABOUT, ASCII, ALT, NOINVERT
|
||||||
|
"C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"C", IDM_COMMAND_MODE, VIRTKEY, ALT, NOINVERT
|
||||||
|
"D", IDM_DICTATION_MODE, VIRTKEY, ALT, NOINVERT
|
||||||
|
"M", IDM_MIC_TOGGLE, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"P", IDM_PLAY, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Dialog
|
||||||
|
//
|
||||||
|
|
||||||
|
IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 113
|
||||||
|
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION "About"
|
||||||
|
FONT 8, "System"
|
||||||
|
BEGIN
|
||||||
|
ICON IDI_DICTPAD,IDC_MYICON,14,9,20,20
|
||||||
|
LTEXT "DictPad Version",IDC_STATIC,49,10,58,8,SS_NOPREFIX
|
||||||
|
LTEXT "(c) 2001 Microsoft Corporation. All rights reserved.",
|
||||||
|
IDC_STATIC,49,20,177,11
|
||||||
|
DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
|
||||||
|
LTEXT "<version>",IDC_ABOUT_DICTPAD_VERSION,107,10,79,8
|
||||||
|
PUSHBUTTON "Components",IDC_ABOUT_COMPONENTS,176,54,49,11,NOT
|
||||||
|
WS_VISIBLE
|
||||||
|
END
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SRGRAMMAR
|
||||||
|
//
|
||||||
|
|
||||||
|
IDR_COMMAND_MODE_CFG SRGRAMMAR DISCARDABLE "chs_cmdmode.cfg"
|
||||||
|
IDR_DICTATION_MODE_CFG SRGRAMMAR DISCARDABLE "chs_dictmode.cfg"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// String Table
|
||||||
|
//
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_APP_TITLE "Dictpad"
|
||||||
|
IDC_DICTPAD "DICTPAD"
|
||||||
|
IDM_PLAY "Play"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDM_FONT "Allow selection of a different font "
|
||||||
|
IDM_DICTATION_MODE "Dictation"
|
||||||
|
IDM_COMMAND_MODE "Command"
|
||||||
|
IDS_WAITING "..."
|
||||||
|
IDS_INVALIDFILEFORMAT "Invalid file format"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDM_MIC_TOGGLE "Grammars active/inactive"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_CANNOTOPEN "This file cannot be opened by Dictpad"
|
||||||
|
IDS_ERRORSAVING "Dictpad encountered an error while saving to this file"
|
||||||
|
IDS_CANNOTSAVE "Error saving to file"
|
||||||
|
IDS_CONFIRMCLOSE "The text of this file has changed since the last save. Do you wish to save this file?"
|
||||||
|
IDS_MICROPHONESETUPWIZARD "Microphone Setup Wizard"
|
||||||
|
IDS_ACCESSDENIED "Cannot save to file: Access denied."
|
||||||
|
IDS_CANNOTSWITCHMODES "Error switching modes"
|
||||||
|
IDS_CANNOTFILENEW "A new file could not be opened."
|
||||||
|
IDS_UPDATEERROR "An error occurred updating the Dictpad document. Dictpad will now exit."
|
||||||
|
IDS_UNSUPPORTEDLANG "Error: The language of the engine is unsupported"
|
||||||
|
END
|
||||||
|
|
255
mp/src/utils/sapi51/Samples/CPP/DictPad/cmdmode.xml
Normal file
255
mp/src/utils/sapi51/Samples/CPP/DictPad/cmdmode.xml
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<GRAMMAR LANGID="409">
|
||||||
|
<DEFINE>
|
||||||
|
<ID NAME="PID_CmdMenu" VAL="1"/>
|
||||||
|
<ID NAME="PID_CmdSysMenu" VAL="2"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuFile" VAL="100"/>
|
||||||
|
<ID NAME="PID_CmdNew" VAL="101"/>
|
||||||
|
<ID NAME="PID_CmdOpen" VAL="102"/>
|
||||||
|
<ID NAME="PID_CmdSave" VAL="103"/>
|
||||||
|
<ID NAME="PID_CmdSaveAs" VAL="104"/>
|
||||||
|
<ID NAME="PID_CmdExit" VAL="105"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuEdit" VAL="200"/>
|
||||||
|
<ID NAME="PID_CmdCut" VAL="201"/>
|
||||||
|
<ID NAME="PID_CmdCopy" VAL="202"/>
|
||||||
|
<ID NAME="PID_CmdPaste" VAL="203"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuVoice" VAL="300"/>
|
||||||
|
<ID NAME="PID_CmdDictationMode" VAL="301"/>
|
||||||
|
<ID NAME="PID_CmdCommandMode" VAL="302"/>
|
||||||
|
<ID NAME="PID_CmdMicrophone" VAL="303"/>
|
||||||
|
<ID NAME="PID_CmdPlayback" VAL="304"/>
|
||||||
|
<ID NAME="PID_CmdAddDeleteWords" VAL="305"/>
|
||||||
|
<ID NAME="PID_CmdSelectWholeWords" VAL="306"/>
|
||||||
|
<ID NAME="PID_CmdSharedRecoEngine" VAL="307"/>
|
||||||
|
<ID NAME="PID_CmdVoiceTraining" VAL="310"/>
|
||||||
|
<ID NAME="PID_CmdMicrophoneSetup" VAL="311"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuHelp" VAL="500"/>
|
||||||
|
<ID NAME="PID_CmdAbout" VAL="501"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdEscape" VAL="903"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNavigationVertical" VAL="1000"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdDirection" VAL="1100"/>
|
||||||
|
<ID NAME="PID_CmdUp" VAL="1001"/>
|
||||||
|
<ID NAME="PID_CmdDown" VAL="1002"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdUnits" VAL="1200"/>
|
||||||
|
<ID NAME="PID_CmdPage" VAL="1201"/>
|
||||||
|
<ID NAME="PID_CmdLine" VAL="1202"/>
|
||||||
|
<ID NAME="PID_CmdParagraph" VAL="1203"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNumber" VAL="1300"/>
|
||||||
|
<ID NAME="PID_Ones" VAL="1301"/>
|
||||||
|
<ID NAME="PID_Tens" VAL="1302"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNavigationOther" VAL="2000"/>
|
||||||
|
<ID NAME="PID_CmdScrollHome" VAL="2001"/>
|
||||||
|
<ID NAME="PID_CmdScrollEnd" VAL="2002"/>
|
||||||
|
<ID NAME="PID_CmdLineEnd" VAL="2003"/>
|
||||||
|
<ID NAME="PID_CmdLineHome" VAL="2004"/>
|
||||||
|
<ID NAME="PID_CmdCharacterLeft" VAL="2005"/>
|
||||||
|
<ID NAME="PID_CmdCharacterRight" VAL="2006"/>
|
||||||
|
<ID NAME="PID_CmdWordLeft" VAL="2007"/>
|
||||||
|
<ID NAME="PID_CmdWordRight" VAL="2008"/>
|
||||||
|
|
||||||
|
</DEFINE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNavigationVertical" ID="PID_CmdNavigationVertical" TOPLEVEL="ACTIVE" EXPORT="1">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<L>
|
||||||
|
<P>scroll</P>
|
||||||
|
<P>move</P>
|
||||||
|
</L>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<RULEREF NAME="PID_CmdNumber" PROPNAME="PID_CmdNumber" PROPID="PID_CmdNumber"/>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdUnits" PROPID="PID_CmdUnits">
|
||||||
|
<P VAL="PID_CmdPage">page</P>
|
||||||
|
<P VAL="PID_CmdPage">pages</P>
|
||||||
|
<P VAL="PID_CmdLine">line</P>
|
||||||
|
<P VAL="PID_CmdLine">lines</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraph</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraphs</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
</P>
|
||||||
|
|
||||||
|
<P>
|
||||||
|
<L PROPNAME="PID_CmdUnits" PROPID="PID_CmdUnits">
|
||||||
|
<P VAL="PID_CmdPage">page</P>
|
||||||
|
<P VAL="PID_CmdLine">line</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraph</P>
|
||||||
|
</L>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNumber" ID="PID_CmdNumber" TOPLEVEL="INACTIVE" EXPORT="1">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="onesfrag"/>
|
||||||
|
</P>
|
||||||
|
<P>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="tens"/>
|
||||||
|
</P>
|
||||||
|
<O>
|
||||||
|
<RULEREF NAME="ones"/>
|
||||||
|
</O>
|
||||||
|
</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNavigationOther" ID="PID_CmdNavigationOther" TOPLEVEL="ACTIVE" EXPORT="1">
|
||||||
|
<L PROPNAME="PID_CmdNavigationOther" PROPID="PID_CmdNavigationOther">
|
||||||
|
<P VAL="PID_CmdScrollHome">go home</P>
|
||||||
|
<P VAL="PID_CmdScrollHome">scroll home</P>
|
||||||
|
<P VAL="PID_CmdScrollEnd">go end</P>
|
||||||
|
<P VAL="PID_CmdScrollEnd">scroll end</P>
|
||||||
|
<P VAL="PID_CmdCharacterLeft">?move left</P>
|
||||||
|
<P VAL="PID_CmdCharacterLeft">scroll left</P>
|
||||||
|
<P VAL="PID_CmdCharacterRight">?move right</P>
|
||||||
|
<P VAL="PID_CmdCharacterRight">scroll right</P>
|
||||||
|
<P VAL="PID_CmdWordLeft">word left</P>
|
||||||
|
<P VAL="PID_CmdWordRight">word right</P>
|
||||||
|
<P VAL="PID_CmdLineEnd">?line end</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line home</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line start</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line beginning</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdMenu" ID="PID_CmdMenu" TOPLEVEL="ACTIVE">
|
||||||
|
<L PROPNAME="PID_CmdMenu" PROPID="PID_CmdMenu">
|
||||||
|
<P VAL="PID_CmdMenuFile">file</P>
|
||||||
|
<P VAL="PID_CmdNew">new</P>
|
||||||
|
<P VAL="PID_CmdOpen">open</P>
|
||||||
|
<P VAL="PID_CmdSave">save</P>
|
||||||
|
<P VAL="PID_CmdSaveAs">save as</P>
|
||||||
|
<P VAL="PID_CmdExit">exit</P>
|
||||||
|
<P VAL="PID_CmdMenuEdit">edit</P>
|
||||||
|
<P VAL="PID_CmdCut">cut</P>
|
||||||
|
<P VAL="PID_CmdCopy">copy</P>
|
||||||
|
<P VAL="PID_CmdPaste">paste</P>
|
||||||
|
<P VAL="PID_CmdMenuVoice">voice</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">listen for dictation</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">?start dictation</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">start dictating</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">end ?of command mode</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">listen for command</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">listen for commands</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">stop dictation</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">end ?of dictation</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">stop dictating</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">?turn microphone off</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">?turn mike off</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">close microphone</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">microphone on</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">grammars active</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">grammars inactive</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">activate grammars</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">deactivate grammars</P>
|
||||||
|
<P VAL="PID_CmdPlayback">play</P>
|
||||||
|
<P VAL="PID_CmdPlayback">play back</P>
|
||||||
|
<P VAL="PID_CmdAddDeleteWords">add ?and delete word</P>
|
||||||
|
<P VAL="PID_CmdSelectWholeWords">select whole word</P>
|
||||||
|
<P VAL="PID_CmdSelectWholeWords">select whole words</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared engine</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared recognition engine</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared reco engine</P>
|
||||||
|
<P VAL="PID_CmdVoiceTraining">?voice training</P>
|
||||||
|
<P VAL="PID_CmdMicrophoneSetup">microphone setup</P>
|
||||||
|
<P VAL="PID_CmdMenuHelp">help</P>
|
||||||
|
<P VAL="PID_CmdAbout">about</P>
|
||||||
|
<P VAL="PID_CmdEscape">cancel</P>
|
||||||
|
<P VAL="PID_CmdEscape">escape</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<!-- Internal number rules -->
|
||||||
|
<RULE NAME="tens">
|
||||||
|
<L PROPNAME="PID_Tens" PROPID="PID_Tens">
|
||||||
|
<P VAL="20">twenty</P>
|
||||||
|
<P VAL="30">thirty</P>
|
||||||
|
<P VAL="40">forty</P>
|
||||||
|
<P VAL="50">fifty</P>
|
||||||
|
<P VAL="60">sixty</P>
|
||||||
|
<P VAL="70">seventy</P>
|
||||||
|
<P VAL="80">eighty</P>
|
||||||
|
<P VAL="90">ninety</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="ones">
|
||||||
|
<L PROPNAME="PID_Ones" PROPID="PID_Ones">
|
||||||
|
<P VAL="1">one</P>
|
||||||
|
<P VAL="2">two</P>
|
||||||
|
<P VAL="3">three</P>
|
||||||
|
<P VAL="4">four</P>
|
||||||
|
<P VAL="5">five</P>
|
||||||
|
<P VAL="6">six</P>
|
||||||
|
<P VAL="7">seven</P>
|
||||||
|
<P VAL="8">eight</P>
|
||||||
|
<P VAL="9">nine</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="onesfrag">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="ones"/>
|
||||||
|
</P>
|
||||||
|
<L PROPNAME="PID_Ones" PROPID="PID_Ones">
|
||||||
|
<P VAL="0">zero</P>
|
||||||
|
<P VAL="10">ten</P>
|
||||||
|
<P VAL="11">eleven</P>
|
||||||
|
<P VAL="12">twelve</P>
|
||||||
|
<P VAL="13">thirteen</P>
|
||||||
|
<P VAL="14">fourteen</P>
|
||||||
|
<P VAL="15">fifteen</P>
|
||||||
|
<P VAL="16">sixteen</P>
|
||||||
|
<P VAL="17">seventeen</P>
|
||||||
|
<P VAL="18">eighteen</P>
|
||||||
|
<P VAL="19">nineteen</P>
|
||||||
|
</L>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
</GRAMMAR>
|
2060
mp/src/utils/sapi51/Samples/CPP/DictPad/dictationrun.cpp
Normal file
2060
mp/src/utils/sapi51/Samples/CPP/DictPad/dictationrun.cpp
Normal file
File diff suppressed because it is too large
Load Diff
141
mp/src/utils/sapi51/Samples/CPP/DictPad/dictationrun.h
Normal file
141
mp/src/utils/sapi51/Samples/CPP/DictPad/dictationrun.h
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* DictationRun.h
|
||||||
|
* This module contains the definition of CDictationRun. CDictationRun
|
||||||
|
* keeps track of the dictation-specific items that go with runs of test
|
||||||
|
* that were dictated to DictPad.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TextRun.h"
|
||||||
|
#include "phrasereplace.h"
|
||||||
|
#include "resultcontainer.h"
|
||||||
|
|
||||||
|
// Forward definition
|
||||||
|
class CResultContainer;
|
||||||
|
|
||||||
|
// Header for serialized CDictationRuns
|
||||||
|
typedef struct DICTHEADER
|
||||||
|
{
|
||||||
|
ULONG cbSize; // Size of the reco result to follow
|
||||||
|
ULONG ulStartElement;
|
||||||
|
ULONG cElements;
|
||||||
|
} DICTHEADER;
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CDictationRun *
|
||||||
|
*---------------*
|
||||||
|
* Description:
|
||||||
|
* This class inherits from CTextRun (in textrun.h). It handles
|
||||||
|
* a consecutive run of text in the document that was dictated.
|
||||||
|
* It can be a full dictated phrase or part of a phrase that
|
||||||
|
* was dictated, but all of the text in a CDictationRun exists
|
||||||
|
* exactly as it had originally been dictated.
|
||||||
|
********************************************************************************/
|
||||||
|
class CDictationRun : public CTextRun
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CDictationRun();
|
||||||
|
virtual ~CDictationRun();
|
||||||
|
|
||||||
|
// Initialization methods
|
||||||
|
HRESULT Initialize( ISpRecoResult &rRecoResult, DICTHEADER *pDictHdr = NULL );
|
||||||
|
HRESULT Initialize( CResultContainer &rResultContainer );
|
||||||
|
HRESULT SetTextRange( ITextRange *pTextRange );
|
||||||
|
|
||||||
|
// Phrase element-related methods
|
||||||
|
HRESULT Split( long *plFirstEnd, long *plSecondBegin,
|
||||||
|
ITextDocument *cpTextDoc, CTextRun **ppTextRun );
|
||||||
|
MERGERESULT Concatenate( CTextRun *pTextRun, bool fConcatAfter );
|
||||||
|
HRESULT CorrectPhraseEltsAndRange( bool fForward, bool *pfCorrectionResult = NULL );
|
||||||
|
// Adjust the phrase element members
|
||||||
|
// and the range so that they are
|
||||||
|
// consistent
|
||||||
|
|
||||||
|
// Alternates methods
|
||||||
|
HRESULT GetAlternatesText( ITextRange *pRangeForAlts,
|
||||||
|
ULONG ulRequestCount,
|
||||||
|
long *plAltStart,
|
||||||
|
long *plAltEnd,
|
||||||
|
WCHAR **ppszCoMemText,
|
||||||
|
bool *apfFitsInRun,
|
||||||
|
ULONG *pcPhrasesReturned );
|
||||||
|
// Get the text of the alternates
|
||||||
|
// for the closest range possible
|
||||||
|
HRESULT GetAltEndpoints( ULONG ulAlt,
|
||||||
|
long *plReplaceStart,
|
||||||
|
long *plReplaceEnd );
|
||||||
|
// Get the start and end of the
|
||||||
|
// range that would be replaced by
|
||||||
|
// alternate ulAlt from the last time
|
||||||
|
// GetAlternatesText() was called
|
||||||
|
HRESULT ChooseAlternate( ULONG ulAlt );
|
||||||
|
// Choose alternate number ulAlt
|
||||||
|
// from the last time GetAlternatesText()
|
||||||
|
// was called
|
||||||
|
void DoneWithAlternates() { m_fAltsGotten = false; }
|
||||||
|
// Called when the last set of alternates
|
||||||
|
// obtained is no longer needed
|
||||||
|
HRESULT OnAlternateCommit( ULONG ulFirstEltToBeReplaced, ULONG cEltsToBeReplaced,
|
||||||
|
ULONG cElementsInPhraseAfterCommit );
|
||||||
|
// Called right before an alternate
|
||||||
|
// is committed somewhere in the
|
||||||
|
// associated result object's phrase
|
||||||
|
|
||||||
|
|
||||||
|
// Playback methods
|
||||||
|
HRESULT Speak( ISpVoice &rVoice ); // Speak the entire block
|
||||||
|
HRESULT Speak( ISpVoice &rVoice, long *plStart, long *plEnd );
|
||||||
|
// Speak part of the block
|
||||||
|
|
||||||
|
// Serialization method
|
||||||
|
HRESULT Serialize( IStream *pStream, ISpRecoContext *pRecoCtxt );
|
||||||
|
// Write the phrase blob to a stream
|
||||||
|
|
||||||
|
// Display attributes methods
|
||||||
|
HRESULT IsConsumeLeadingSpaces( const long lPos, bool *pfConsumeLeadingSpaces );
|
||||||
|
// Do leading spaces need to be
|
||||||
|
// consumed at lPos?
|
||||||
|
HRESULT HowManySpacesAfter( const long lPos, UINT *puiSpaces );
|
||||||
|
// How many spaces would need to be
|
||||||
|
// at lPos if new text were inserted there?
|
||||||
|
|
||||||
|
bool IsDict() { return true; };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
HRESULT FindNearestWholeElementRange( long lStart,
|
||||||
|
long lEnd,
|
||||||
|
long *plResultStart,
|
||||||
|
long *plResultEnd,
|
||||||
|
ULONG *pulStartElement,
|
||||||
|
ULONG *pcElements );
|
||||||
|
// Finds the nearest range containing
|
||||||
|
// pRange that contains entire elements
|
||||||
|
|
||||||
|
// data members
|
||||||
|
private:
|
||||||
|
|
||||||
|
ULONG m_ulStartElement; // Where in the RecoResult this dictation run starts
|
||||||
|
ULONG m_cElements; // How many elements are in this run
|
||||||
|
|
||||||
|
bool m_fAltsGotten; // Whether alternates have been requested for some range
|
||||||
|
// of elements
|
||||||
|
ULONG m_ulStartAltElt; // These two members indicate the range of elements
|
||||||
|
ULONG m_cAltElt; // for which alternates were last requested
|
||||||
|
|
||||||
|
CPhraseReplacement *m_pPhraseReplacement; // Phrase replacement (ITN) info
|
||||||
|
ULONG *m_pulElementOffsets; // Where each element starts
|
||||||
|
// relative to the start of the range
|
||||||
|
CResultContainer *m_pResultContainer; // Holds the result object
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
|
||||||
|
bool ContainsNonWhitespace( const WCHAR *pwsz );// Return true iff some
|
||||||
|
// character in the string
|
||||||
|
// is not whitespace
|
||||||
|
|
15
mp/src/utils/sapi51/Samples/CPP/DictPad/dictmode.xml
Normal file
15
mp/src/utils/sapi51/Samples/CPP/DictPad/dictmode.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<GRAMMAR LANGID="409">
|
||||||
|
<DEFINE>
|
||||||
|
<ID NAME="PID_DictMode" VAL="1"/>
|
||||||
|
<ID NAME="PID_DictCommand" VAL="901"/>
|
||||||
|
|
||||||
|
</DEFINE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_DictMode" ID="PID_DictMode" TOPLEVEL="ACTIVE">
|
||||||
|
<L PROPNAME="PID_DictMode" PROPID="PID_DictMode">
|
||||||
|
<P VAL="PID_DictCommand">command</P>
|
||||||
|
<P VAL="PID_DictCommand">computer</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
</GRAMMAR>
|
2135
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.cpp
Normal file
2135
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.cpp
Normal file
File diff suppressed because it is too large
Load Diff
443
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.dsp
Normal file
443
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.dsp
Normal file
@ -0,0 +1,443 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="dictpad" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||||
|
|
||||||
|
CFG=dictpad - Win32 Debug x86
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "dictpad.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "dictpad.mak" CFG="dictpad - Win32 Debug x86"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "dictpad - Win32 Debug x86" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE "dictpad - Win32 Release x86" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath "Desktop"
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "dictpad - Win32 Debug x86"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "dictpad___Win32_Debug_x86"
|
||||||
|
# PROP BASE Intermediate_Dir "dictpad___Win32_Debug_x86"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug_x86"
|
||||||
|
# PROP Intermediate_Dir "Debug_x86"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\include" /I "..\..\..\..\ddk\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\ddk\include" /I "..\..\..\include" /I "..\Common" /I "..\..\Common" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D _WIN32_WINNT=0x0500 /FR /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib version.lib imm32.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"LIBCMTD" /pdbtype:sept /libpath:"..\..\..\lib\i386"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "dictpad - Win32 Release x86"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "dictpad___Win32_Release_x86"
|
||||||
|
# PROP BASE Intermediate_Dir "dictpad___Win32_Release_x86"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release_x86"
|
||||||
|
# PROP Intermediate_Dir "Release_x86"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /I "..\..\..\..\ddk\include" /I "..\..\..\..\patch\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /Zi /O2 /I "..\Common" /I "..\..\Common" /I "..\..\..\..\ddk\include" /I "..\..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D _WIN32_WINNT=0x0500 /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib version.lib imm32.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"LIBCMT" /libpath:"..\..\..\lib\i386" /debugtype:cv,fixup
|
||||||
|
# SUBTRACT LINK32 /pdb:none
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "dictpad - Win32 Debug x86"
|
||||||
|
# Name "dictpad - Win32 Release x86"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\candidatelist.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\common\ComponentVersionDlg.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\DictationRun.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dictpad.cpp
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "dictpad - Win32 Debug x86"
|
||||||
|
|
||||||
|
# ADD CPP /I "..\common"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "dictpad - Win32 Release x86"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dictpad.rc
|
||||||
|
# ADD BASE RSC /l 0x409
|
||||||
|
# ADD RSC /l 0x409 /i "..\..\..\..\build" /i "..\Common" /i "..\..\Common"
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dictpad_sapi.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\phrasereplace.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\recomgr.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\resultcontainer.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\StdAfx.cpp
|
||||||
|
# ADD BASE CPP /Yc"stdafx.h"
|
||||||
|
# ADD CPP /Yc"stdafx.h"
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\textrun.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\TextRunList.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\tom_i.c
|
||||||
|
# SUBTRACT BASE CPP /YX /Yc /Yu
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\candidatelist.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\DictationRun.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dictpad.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\phrasereplace.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\recomgr.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\resource.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\resultcontainer.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\StdAfx.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\textrun.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\TextRunList.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\bitmap1.bmp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cursor1.cur
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dictpad.ico
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\small.ico
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Grammar"
|
||||||
|
|
||||||
|
# PROP Default_Filter "xml"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\chs_cmdmode.xml
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "dictpad - Win32 Debug x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
InputDir=.
|
||||||
|
InputPath=.\chs_cmdmode.xml
|
||||||
|
|
||||||
|
"$(InputDir)\chs_cmdmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
..\..\..\bin\gc $(InputPath)
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "dictpad - Win32 Release x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
InputDir=.
|
||||||
|
InputPath=.\chs_cmdmode.xml
|
||||||
|
|
||||||
|
"$(InputDir)\chs_cmdmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
..\..\..\bin\gc $(InputPath)
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\chs_dictmode.xml
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "dictpad - Win32 Debug x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
InputDir=.
|
||||||
|
InputPath=.\chs_dictmode.xml
|
||||||
|
|
||||||
|
"$(InputDir)\chs_dictmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
..\..\..\bin\gc $(InputPath)
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "dictpad - Win32 Release x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
InputDir=.
|
||||||
|
InputPath=.\chs_dictmode.xml
|
||||||
|
|
||||||
|
"$(InputDir)\chs_dictmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
..\..\..\bin\gc $(InputPath)
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cmdmode.xml
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "dictpad - Win32 Debug x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
ProjDir=.
|
||||||
|
InputPath=.\cmdmode.xml
|
||||||
|
InputName=cmdmode
|
||||||
|
|
||||||
|
BuildCmds= \
|
||||||
|
..\..\..\bin\gc /h cmdmode.h $(InputName)
|
||||||
|
|
||||||
|
"$(ProjDir)\cmdmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
$(BuildCmds)
|
||||||
|
|
||||||
|
"$(ProjDir)\cmdmode.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
$(BuildCmds)
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "dictpad - Win32 Release x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
ProjDir=.
|
||||||
|
InputPath=.\cmdmode.xml
|
||||||
|
InputName=cmdmode
|
||||||
|
|
||||||
|
BuildCmds= \
|
||||||
|
..\..\..\bin\gc /h cmdmode.h $(InputName)
|
||||||
|
|
||||||
|
"$(ProjDir)\cmdmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
$(BuildCmds)
|
||||||
|
|
||||||
|
"$(ProjDir)\cmdmode.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
$(BuildCmds)
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dictmode.xml
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "dictpad - Win32 Debug x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
ProjDir=.
|
||||||
|
InputPath=.\dictmode.xml
|
||||||
|
InputName=dictmode
|
||||||
|
|
||||||
|
BuildCmds= \
|
||||||
|
..\..\..\bin\gc /h dictmode.h $(InputName)
|
||||||
|
|
||||||
|
"$(ProjDir)\dictmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
$(BuildCmds)
|
||||||
|
|
||||||
|
"$(ProjDir)\dictmode.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
$(BuildCmds)
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "dictpad - Win32 Release x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
ProjDir=.
|
||||||
|
InputPath=.\dictmode.xml
|
||||||
|
InputName=dictmode
|
||||||
|
|
||||||
|
BuildCmds= \
|
||||||
|
..\..\..\bin\gc /h dictmode.h $(InputName)
|
||||||
|
|
||||||
|
"$(ProjDir)\dictmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
$(BuildCmds)
|
||||||
|
|
||||||
|
"$(ProjDir)\dictmode.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
$(BuildCmds)
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\jpn_cmdmode.xml
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "dictpad - Win32 Debug x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
InputDir=.
|
||||||
|
InputPath=.\jpn_cmdmode.xml
|
||||||
|
|
||||||
|
"$(InputDir)\jpn_cmdmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
..\..\..\bin\gc $(InputPath)
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "dictpad - Win32 Release x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
InputDir=.
|
||||||
|
InputPath=.\jpn_cmdmode.xml
|
||||||
|
|
||||||
|
"$(InputDir)\jpn_cmdmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
..\..\..\bin\gc $(InputPath)
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\jpn_dictmode.xml
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "dictpad - Win32 Debug x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
InputDir=.
|
||||||
|
InputPath=.\jpn_dictmode.xml
|
||||||
|
|
||||||
|
"$(InputDir)\jpn_dictmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
..\..\..\bin\gc $(InputPath)
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "dictpad - Win32 Release x86"
|
||||||
|
|
||||||
|
# Begin Custom Build
|
||||||
|
InputDir=.
|
||||||
|
InputPath=.\jpn_dictmode.xml
|
||||||
|
|
||||||
|
"$(InputDir)\jpn_dictmode.cfg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
..\..\..\bin\gc $(InputPath)
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cmdmode.cfg
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dictmode.cfg
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ReadMe.txt
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
202
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.h
Normal file
202
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.h
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* DictPad.h
|
||||||
|
* This module contains the base definitions for the DictPad SAPI 5
|
||||||
|
* premier app.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "resource.h"
|
||||||
|
#include "candidatelist.h"
|
||||||
|
|
||||||
|
// Flags that determine the state of the app
|
||||||
|
typedef enum DPFLAGS
|
||||||
|
{
|
||||||
|
DP_DICTATION_MODE = ( 1L << 0 ), // Toggles between dictation and command mode
|
||||||
|
DP_WHOLE_WORD_SEL = ( 1L << 1 ), // Indicates that whole words should be selected
|
||||||
|
DP_MICROPHONE_ON = ( 1L << 2 ), // Indicates that the "mic" is on (really that
|
||||||
|
// the appropriate grammars are active
|
||||||
|
DP_SHARED_RECOGNIZER = ( 1L << 3 ), // Shared reco engine (false if engine is inproc)
|
||||||
|
DP_IS_SPEAKING = ( 1L << 4 ), // Indicates that we are in the midst of a playback
|
||||||
|
DP_GRAMMARS_ACTIVE = ( 1L << 5 ), // Indicates the the "mic" is on
|
||||||
|
DP_JUST_PASTED_TEXT = ( 1L << 6 ), // Indicates that text has just been pasted
|
||||||
|
DP_SKIP_UPDATE = ( 1L << 7 ) // Indicates that selection changes should not be processed
|
||||||
|
} DPFLAGS;
|
||||||
|
|
||||||
|
// There are three grammars loaded
|
||||||
|
typedef enum GRAMMARIDS
|
||||||
|
{
|
||||||
|
GID_DICTATION, // ID for the dictation grammar
|
||||||
|
GID_DICTATIONCC, // ID for the C&C grammar that's active during dictation
|
||||||
|
GID_CC // ID for the C&C grammar that's active when dictation is not
|
||||||
|
};
|
||||||
|
|
||||||
|
// State having to do with the text selection
|
||||||
|
typedef struct SELINFO
|
||||||
|
{
|
||||||
|
SELCHANGE selchange; // SELCHANGE struct
|
||||||
|
long lTextLen; // Total text length
|
||||||
|
} SELINFO;
|
||||||
|
|
||||||
|
// State having to do with an ongoing playback
|
||||||
|
typedef struct SPEAKINFO
|
||||||
|
{
|
||||||
|
long lSelStart, lSelEnd;
|
||||||
|
ITextRange *pSpeakRange;
|
||||||
|
PTEXTRUNNODE pCurrentNode;
|
||||||
|
ULONG ulCurrentStream; // The stream number we are currently on
|
||||||
|
} SPEAKINFO;
|
||||||
|
|
||||||
|
// A way of mapping between recognized voice command and window messages.
|
||||||
|
// The details of what gets executed in response to voice-enable menus is very consistent and predictable.
|
||||||
|
// Effectively, we will send a message to the client window, simulating the menu item itself.
|
||||||
|
// This structure is used for bundling these details.
|
||||||
|
// An instance of this map is created in dictpad_sapi.cpp
|
||||||
|
struct PROPERTYMAP
|
||||||
|
{
|
||||||
|
DWORD dwPropertyID; // The specific property Id
|
||||||
|
UINT uiMessage; // Speicific msg that will be sent to the apps client window
|
||||||
|
WPARAM wParam; // First param - value is dependent upon the msg
|
||||||
|
LPARAM lParam; // Second param - value is dependent upon the msg
|
||||||
|
};
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
#define MAX_LOADSTRING 1000
|
||||||
|
#define WM_DICTRECOEVENT WM_USER + 1
|
||||||
|
#define WM_CCRECOEVENT WM_USER + 2
|
||||||
|
#define WM_TTSEVENT WM_USER + 3
|
||||||
|
#define WM_STOPUPDATE WM_USER + 4
|
||||||
|
#define WM_STARTUPDATE WM_USER + 5
|
||||||
|
#define WM_UPDATEALTSBUTTON WM_USER + 6
|
||||||
|
|
||||||
|
class CDictationPad
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CDictationPad( HINSTANCE hInst = NULL );
|
||||||
|
~CDictationPad();
|
||||||
|
|
||||||
|
// Functions for running Dictpad (in dictpad.cpp)
|
||||||
|
BOOL Initialize( int nCmdShow, LPSTR lpCmdLine );
|
||||||
|
int Run( void );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// In dictpad.cpp:
|
||||||
|
|
||||||
|
// Window proc
|
||||||
|
static LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
|
||||||
|
|
||||||
|
// Initialization methods
|
||||||
|
BOOL InitializeWindow( HWND hWnd );
|
||||||
|
void SetTooltipText( LPARAM lParam );
|
||||||
|
|
||||||
|
// Methods to process typed input and other notifications from the edit window
|
||||||
|
HRESULT UpdateList( long lStart, long lEnd ); // Updates the list by inserting a block
|
||||||
|
void ProcessMsgFilter( MSGFILTER *pMsgFilter ); // Handle the various notificaton events
|
||||||
|
// that we were interested in
|
||||||
|
HRESULT ProcessSelChange( SELCHANGE *pSelChange);
|
||||||
|
// Handle notification of selection change
|
||||||
|
// (this is how keyboard input gets processed)
|
||||||
|
|
||||||
|
// Playback
|
||||||
|
HRESULT DoPlay(); // Executes a playback
|
||||||
|
HRESULT StartSpeaking( long lStartSpeakRange, // Called before a playback starts
|
||||||
|
long lEndSpeakRange);
|
||||||
|
void EndSpeaking(); // Called when a playback is through
|
||||||
|
|
||||||
|
// File new/open/save/close
|
||||||
|
HRESULT DoFileNew(); // Opens a new file
|
||||||
|
HRESULT DoFileOpen( LPTSTR lpFileName ); // Opens a file from GetOpenFileName
|
||||||
|
HRESULT DoFileSave( bool fTextOnly = false ); // Saves a file in the appropriate format
|
||||||
|
HRESULT DoFileSaveAs(); // Gets a name from GetSaveFileName and saves
|
||||||
|
HRESULT DoFileClose(); // Closes the file if there is currently one open
|
||||||
|
|
||||||
|
// In dictpad_sapi.cpp:
|
||||||
|
|
||||||
|
// Initialization methods
|
||||||
|
HRESULT InitializeSAPIObjs(); // Set up the SAPI objects
|
||||||
|
HRESULT InitSAPICallback( HWND hWnd ); // Hook up the client window for SAPI notifications
|
||||||
|
HRESULT LoadGrammars(); // Load the various grammars
|
||||||
|
|
||||||
|
// SR and TTS notification functions
|
||||||
|
bool SRDictEventHandler( void ); // Handle notifications from the dictation context
|
||||||
|
bool SRCCEventHandler( void ); // Handle notifications from the C&C context
|
||||||
|
void TTSEventHandler( void ); // Handle notifications from the voice
|
||||||
|
void SetSREventInterest( bool fOn ); // Sets/unsets interest in SR notification events
|
||||||
|
|
||||||
|
// Methods to process events from the SR engine
|
||||||
|
bool ProcessDictationModeCommands( ISpRecoResult &rResult );
|
||||||
|
// Process commands recognized while in dictation mode
|
||||||
|
bool ProcessCommandModeCommands( ISpRecoResult &rResult );
|
||||||
|
// Process commands recognized while in command mode
|
||||||
|
bool ProcessDictation( ISpRecoResult &rResult, int eEventId );
|
||||||
|
// Process dictation recognitions
|
||||||
|
bool ProcessDictationHypothesis( ISpRecoResult &rResult );
|
||||||
|
// Process dictation hypotheses
|
||||||
|
|
||||||
|
// Switching between the two recognition contexts
|
||||||
|
HRESULT SetMode( bool fDictationMode ); // Switches between dictation and command modes
|
||||||
|
|
||||||
|
// Controlling the "mic" (really, whether grammar rules are active)
|
||||||
|
HRESULT SetGrammarState( BOOL bOn ); // Sets the grammar rules to the desired state
|
||||||
|
|
||||||
|
// Add/delete Words UI
|
||||||
|
HRESULT RunAddDeleteUI(); // Starts up the Add/Delete words UI
|
||||||
|
// with in params as appropriate
|
||||||
|
private:
|
||||||
|
// Win32-related handles
|
||||||
|
HACCEL m_hAccelTable; // handle to the accelerators
|
||||||
|
HINSTANCE m_hInst; // handle to the current instance
|
||||||
|
HMODULE m_hRtfLib; // handle to the rich edit control dll
|
||||||
|
HWND m_hClient; // handle to the app's client window
|
||||||
|
HWND m_hEdit; // handle to the rich edit control
|
||||||
|
HWND m_hToolBar; // handle to the toolbar
|
||||||
|
HWND m_hStatusBar; // handle to the status bar
|
||||||
|
HFONT m_hFont; // handle to the current font
|
||||||
|
HWND m_hAltsButton; // handle to alternates UI button
|
||||||
|
|
||||||
|
// Application state
|
||||||
|
DWORD m_dwFlags; // DPFLAGS (see above)
|
||||||
|
SELINFO m_LastSelInfo; // Information on the last selection
|
||||||
|
SELINFO m_CurSelInfo; // Information on the current selection
|
||||||
|
SPEAKINFO m_SpeakInfo; // Information about the current speaking state
|
||||||
|
TCHAR *m_pszFile; // Name of the current file
|
||||||
|
|
||||||
|
|
||||||
|
// Richedit/TOM
|
||||||
|
CComPtr<IRichEditOle> m_cpRichEdit; // OLE interface to the rich edit control
|
||||||
|
CComPtr<ITextDocument> m_cpTextDoc;
|
||||||
|
CComPtr<ITextSelection> m_cpTextSel;
|
||||||
|
|
||||||
|
// SAPI objects
|
||||||
|
CComPtr<ISpRecognizer> m_cpRecoEngine; // SR engine
|
||||||
|
CComPtr<ISpRecoContext> m_cpDictRecoCtxt; // Recognition context for dictation
|
||||||
|
CComPtr<ISpRecoContext> m_cpCCRecoCtxt; // Recognition context for C&C
|
||||||
|
CComPtr<ISpRecoGrammar> m_cpDictGrammar; // Dictation grammar
|
||||||
|
CComPtr<ISpRecoGrammar> m_cpDictCCGrammar; // Grammar for the few commands that are accessible while dictating
|
||||||
|
CComPtr<ISpRecoGrammar> m_cpCCGrammar; // Grammar for full command & control mode
|
||||||
|
CComPtr<ISpVoice> m_cpVoice; // TTS voice
|
||||||
|
|
||||||
|
// Event interests
|
||||||
|
const ULONGLONG m_ullDictInterest; // Events in which Dictpad will be interested in
|
||||||
|
const ULONGLONG m_ullCCInterest;
|
||||||
|
|
||||||
|
// Classes related to CDictationPad
|
||||||
|
CTextRunList *m_pTextRunList; // List of dictated and non-dictated runs (textrunlist.cpp)
|
||||||
|
CRecoEventMgr *m_pRecoEventMgr; // Handles placement of recognized text (recomgr.cpp)
|
||||||
|
CCandidateList *m_pCandidateList; // Handles alternates UI (candidatelist.cpp)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--- Function Prototypes -----------------------------------------------------
|
||||||
|
|
||||||
|
// In dictpad.cpp
|
||||||
|
LRESULT CALLBACK About( HWND, UINT, WPARAM, LPARAM );
|
||||||
|
DWORD CALLBACK EditStreamCallbackReadIn( DWORD dwCookie, LPBYTE pbBuff, ULONG cb, ULONG *pcb );
|
||||||
|
DWORD CALLBACK EditStreamCallbackWriteOut( DWORD dwCookie, LPBYTE pbBuff, ULONG cb, ULONG *pcb );
|
||||||
|
int MessageBoxFromResource( HWND hWnd, UINT uID, LPCTSTR lpCaption, UINT uType );
|
||||||
|
|
||||||
|
// In dictpad_sapi.cpp
|
||||||
|
void HighlightAndBringIntoView( ITextDocument &rTextDoc, long lStart, long lEnd );
|
||||||
|
void DumpCommandToScreen( HWND hwndClient, ISpPhrase &rPhrase );
|
||||||
|
|
BIN
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.ico
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
257
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.rc
Normal file
257
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad.rc
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
//Microsoft Developer Studio generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||||
|
#include "windows.h"
|
||||||
|
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||||
|
#include "resource.h"
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (U.S.) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||||
|
#ifdef _WIN32
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
#pragma code_page(1252)
|
||||||
|
#endif //_WIN32
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Icon
|
||||||
|
//
|
||||||
|
|
||||||
|
// Icon with lowest ID value placed first to ensure application icon
|
||||||
|
// remains consistent on all systems.
|
||||||
|
IDI_DICTPAD ICON DISCARDABLE "dictpad.ICO"
|
||||||
|
IDI_SMALL ICON DISCARDABLE "SMALL.ICO"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Menu
|
||||||
|
//
|
||||||
|
|
||||||
|
IDC_DICTPAD MENU DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
POPUP "&File"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "&New\tCtrl+N", ID_FILE_NEW
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
|
||||||
|
MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
|
||||||
|
MENUITEM "Save &As...", ID_FILE_SAVEAS
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "E&xit\tCtrl+X", IDM_EXIT
|
||||||
|
END
|
||||||
|
POPUP "&Edit"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
|
||||||
|
MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
|
||||||
|
MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
|
||||||
|
END
|
||||||
|
POPUP "&Voice"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Listen for &Dictation", IDM_DICTATION_MODE, CHECKED
|
||||||
|
MENUITEM "Listen for &Commands", IDM_COMMAND_MODE
|
||||||
|
MENUITEM "&Grammars active\tCtrl+M", IDM_MIC_TOGGLE
|
||||||
|
MENUITEM "Play&back\tCtrl+P", IDM_PLAY
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Add/Delete Word(s)...", IDM_ADDREMOVEWORDS
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "Select &Whole Words", IDM_WHOLE_WORDS, CHECKED
|
||||||
|
MENUITEM "S&hared recognition engine", IDM_SHAREDENGINE
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Voice Training...", IDM_VOICE_TRAINING
|
||||||
|
MENUITEM "Micro&phone Setup...", IDM_MICROPHONE_SETUP
|
||||||
|
END
|
||||||
|
POPUP "&Help"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "&About ...", IDM_ABOUT
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Accelerator
|
||||||
|
//
|
||||||
|
|
||||||
|
IDC_DICTPAD ACCELERATORS MOVEABLE PURE
|
||||||
|
BEGIN
|
||||||
|
"/", IDM_ABOUT, ASCII, ALT, NOINVERT
|
||||||
|
"?", IDM_ABOUT, ASCII, ALT, NOINVERT
|
||||||
|
"C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"C", IDM_COMMAND_MODE, VIRTKEY, ALT, NOINVERT
|
||||||
|
"D", IDM_DICTATION_MODE, VIRTKEY, ALT, NOINVERT
|
||||||
|
"M", IDM_MIC_TOGGLE, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"P", IDM_PLAY, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
"X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Dialog
|
||||||
|
//
|
||||||
|
|
||||||
|
IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 62
|
||||||
|
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION "About"
|
||||||
|
FONT 8, "System"
|
||||||
|
BEGIN
|
||||||
|
ICON IDI_DICTPAD,IDC_MYICON,14,9,20,20
|
||||||
|
LTEXT "DictPad ",IDC_STATIC,49,10,58,8,SS_NOPREFIX
|
||||||
|
LTEXT "(c) 2001 Microsoft Corporation.",IDC_STATIC,49,23,177,
|
||||||
|
11
|
||||||
|
DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
|
||||||
|
LTEXT "All rights reserved.",IDC_STATIC,49,39,177,11
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
2 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||||
|
"#include ""windows.h""\r\n"
|
||||||
|
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||||
|
"#include ""resource.h""\r\n"
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"#include ""SapiSDKCommon.rc2""\r\n"
|
||||||
|
"#include ""chs_dictpad.rc""\r\n"
|
||||||
|
"#include ""jpn_dictpad.rc""\r\n"
|
||||||
|
"#include ""version.rc2""\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"#include ""chs_dictpad.rc""\r\n"
|
||||||
|
"#include ""jpn_dictpad.rc""\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
1 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SRGRAMMAR
|
||||||
|
//
|
||||||
|
|
||||||
|
IDR_COMMAND_MODE_CFG SRGRAMMAR DISCARDABLE "cmdmode.cfg"
|
||||||
|
IDR_DICTATION_MODE_CFG SRGRAMMAR DISCARDABLE "dictmode.cfg"
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Toolbar
|
||||||
|
//
|
||||||
|
|
||||||
|
IDR_TOOLBAR TOOLBAR DISCARDABLE 16, 16
|
||||||
|
BEGIN
|
||||||
|
BUTTON IDB_DICTMODE
|
||||||
|
BUTTON IDB_COMMANDMODE
|
||||||
|
SEPARATOR
|
||||||
|
BUTTON IDB_PLAY
|
||||||
|
BUTTON IDB_MICTOGGLE
|
||||||
|
BUTTON 65535
|
||||||
|
BUTTON 65535
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Bitmap
|
||||||
|
//
|
||||||
|
|
||||||
|
IDR_TOOLBAR BITMAP DISCARDABLE "toolbar1.bmp"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// String Table
|
||||||
|
//
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_APP_TITLE "Dictpad"
|
||||||
|
IDC_DICTPAD "DICTPAD"
|
||||||
|
IDM_PLAY "Play"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDM_FONT "Allow selection of a different font "
|
||||||
|
IDM_DICTATION_MODE "Dictation"
|
||||||
|
IDM_COMMAND_MODE "Command"
|
||||||
|
IDS_ADD "Add"
|
||||||
|
IDS_CHANGE "Change"
|
||||||
|
IDS_NONEWWORDS "No new words"
|
||||||
|
IDS_NOWORDSADDED "No new words have been added to the lexicon."
|
||||||
|
IDS_WAITING "..."
|
||||||
|
IDS_INVALIDFILEFORMAT "Invalid file format"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDM_MIC_TOGGLE "Grammars active/inactive"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_CANNOTOPEN "This file cannot be opened by Dictpad"
|
||||||
|
IDS_ERRORSAVING "Dictpad encountered an error while saving to this file"
|
||||||
|
IDS_CANNOTSAVE "Error saving to file"
|
||||||
|
IDS_CONFIRMCLOSE "The text of this file has changed since the last save. Do you wish to save this file?"
|
||||||
|
IDS_MICROPHONESETUPWIZARD "Microphone Setup Wizard"
|
||||||
|
IDS_ACCESSDENIED "Cannot save to file: Access denied."
|
||||||
|
IDS_CANNOTSWITCHMODES "Error switching modes"
|
||||||
|
IDS_CANNOTFILENEW "A new file could not be opened."
|
||||||
|
IDS_UPDATEERROR "An error occurred updating the Dictpad document. Dictpad will now exit."
|
||||||
|
IDS_UNSUPPORTEDLANG "Error: The language of the engine is unsupported"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (U.S.) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
#include "SapiSDKCommon.rc2"
|
||||||
|
#include "chs_dictpad.rc"
|
||||||
|
#include "jpn_dictpad.rc"
|
||||||
|
#include "version.rc2"
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
2024
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad_sapi.cpp
Normal file
2024
mp/src/utils/sapi51/Samples/CPP/DictPad/dictpad_sapi.cpp
Normal file
File diff suppressed because it is too large
Load Diff
255
mp/src/utils/sapi51/Samples/CPP/DictPad/jpn_cmdmode.xml
Normal file
255
mp/src/utils/sapi51/Samples/CPP/DictPad/jpn_cmdmode.xml
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<GRAMMAR LANGID="411">
|
||||||
|
<DEFINE>
|
||||||
|
<ID NAME="PID_CmdMenu" VAL="1"/>
|
||||||
|
<ID NAME="PID_CmdSysMenu" VAL="2"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuFile" VAL="100"/>
|
||||||
|
<ID NAME="PID_CmdNew" VAL="101"/>
|
||||||
|
<ID NAME="PID_CmdOpen" VAL="102"/>
|
||||||
|
<ID NAME="PID_CmdSave" VAL="103"/>
|
||||||
|
<ID NAME="PID_CmdSaveAs" VAL="104"/>
|
||||||
|
<ID NAME="PID_CmdExit" VAL="105"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuEdit" VAL="200"/>
|
||||||
|
<ID NAME="PID_CmdCut" VAL="201"/>
|
||||||
|
<ID NAME="PID_CmdCopy" VAL="202"/>
|
||||||
|
<ID NAME="PID_CmdPaste" VAL="203"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuVoice" VAL="300"/>
|
||||||
|
<ID NAME="PID_CmdDictationMode" VAL="301"/>
|
||||||
|
<ID NAME="PID_CmdCommandMode" VAL="302"/>
|
||||||
|
<ID NAME="PID_CmdMicrophone" VAL="303"/>
|
||||||
|
<ID NAME="PID_CmdPlayback" VAL="304"/>
|
||||||
|
<ID NAME="PID_CmdAddDeleteWords" VAL="305"/>
|
||||||
|
<ID NAME="PID_CmdSelectWholeWords" VAL="306"/>
|
||||||
|
<ID NAME="PID_CmdSharedRecoEngine" VAL="307"/>
|
||||||
|
<ID NAME="PID_CmdVoiceTraining" VAL="310"/>
|
||||||
|
<ID NAME="PID_CmdMicrophoneSetup" VAL="311"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdMenuHelp" VAL="500"/>
|
||||||
|
<ID NAME="PID_CmdAbout" VAL="501"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdEscape" VAL="903"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNavigationVertical" VAL="1000"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdDirection" VAL="1100"/>
|
||||||
|
<ID NAME="PID_CmdUp" VAL="1001"/>
|
||||||
|
<ID NAME="PID_CmdDown" VAL="1002"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdUnits" VAL="1200"/>
|
||||||
|
<ID NAME="PID_CmdPage" VAL="1201"/>
|
||||||
|
<ID NAME="PID_CmdLine" VAL="1202"/>
|
||||||
|
<ID NAME="PID_CmdParagraph" VAL="1203"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNumber" VAL="1300"/>
|
||||||
|
<ID NAME="PID_Ones" VAL="1301"/>
|
||||||
|
<ID NAME="PID_Tens" VAL="1302"/>
|
||||||
|
|
||||||
|
<ID NAME="PID_CmdNavigationOther" VAL="2000"/>
|
||||||
|
<ID NAME="PID_CmdScrollHome" VAL="2001"/>
|
||||||
|
<ID NAME="PID_CmdScrollEnd" VAL="2002"/>
|
||||||
|
<ID NAME="PID_CmdLineEnd" VAL="2003"/>
|
||||||
|
<ID NAME="PID_CmdLineHome" VAL="2004"/>
|
||||||
|
<ID NAME="PID_CmdCharacterLeft" VAL="2005"/>
|
||||||
|
<ID NAME="PID_CmdCharacterRight" VAL="2006"/>
|
||||||
|
<ID NAME="PID_CmdWordLeft" VAL="2007"/>
|
||||||
|
<ID NAME="PID_CmdWordRight" VAL="2008"/>
|
||||||
|
|
||||||
|
</DEFINE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNavigationVertical" ID="PID_CmdNavigationVertical" TOPLEVEL="ACTIVE" EXPORT="1">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<L>
|
||||||
|
<P>scroll</P>
|
||||||
|
<P>move</P>
|
||||||
|
</L>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<RULEREF NAME="PID_CmdNumber" PROPNAME="PID_CmdNumber" PROPID="PID_CmdNumber"/>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdUnits" PROPID="PID_CmdUnits">
|
||||||
|
<P VAL="PID_CmdPage">page</P>
|
||||||
|
<P VAL="PID_CmdPage">pages</P>
|
||||||
|
<P VAL="PID_CmdLine">line</P>
|
||||||
|
<P VAL="PID_CmdLine">lines</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraph</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraphs</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
<O>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</O>
|
||||||
|
</P>
|
||||||
|
|
||||||
|
<P>
|
||||||
|
<L PROPNAME="PID_CmdUnits" PROPID="PID_CmdUnits">
|
||||||
|
<P VAL="PID_CmdPage">page</P>
|
||||||
|
<P VAL="PID_CmdLine">line</P>
|
||||||
|
<P VAL="PID_CmdParagraph">paragraph</P>
|
||||||
|
</L>
|
||||||
|
<L PROPNAME="PID_CmdDirection" PROPID="PID_CmdDirection">
|
||||||
|
<P VAL="PID_CmdUp">up</P>
|
||||||
|
<P VAL="PID_CmdUp">backward</P>
|
||||||
|
<P VAL="PID_CmdUp">backwards</P>
|
||||||
|
<P VAL="PID_CmdDown">down</P>
|
||||||
|
<P VAL="PID_CmdDown">forward</P>
|
||||||
|
<P VAL="PID_CmdDown">forwards</P>
|
||||||
|
</L>
|
||||||
|
</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNumber" ID="PID_CmdNumber" TOPLEVEL="INACTIVE" EXPORT="1">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="onesfrag"/>
|
||||||
|
</P>
|
||||||
|
<P>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="tens"/>
|
||||||
|
</P>
|
||||||
|
<O>
|
||||||
|
<RULEREF NAME="ones"/>
|
||||||
|
</O>
|
||||||
|
</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdNavigationOther" ID="PID_CmdNavigationOther" TOPLEVEL="ACTIVE" EXPORT="1">
|
||||||
|
<L PROPNAME="PID_CmdNavigationOther" PROPID="PID_CmdNavigationOther">
|
||||||
|
<P VAL="PID_CmdScrollHome">go home</P>
|
||||||
|
<P VAL="PID_CmdScrollHome">scroll home</P>
|
||||||
|
<P VAL="PID_CmdScrollEnd">go end</P>
|
||||||
|
<P VAL="PID_CmdScrollEnd">scroll end</P>
|
||||||
|
<P VAL="PID_CmdCharacterLeft">?move left</P>
|
||||||
|
<P VAL="PID_CmdCharacterLeft">scroll left</P>
|
||||||
|
<P VAL="PID_CmdCharacterRight">?move right</P>
|
||||||
|
<P VAL="PID_CmdCharacterRight">scroll right</P>
|
||||||
|
<P VAL="PID_CmdWordLeft">word left</P>
|
||||||
|
<P VAL="PID_CmdWordRight">word right</P>
|
||||||
|
<P VAL="PID_CmdLineEnd">?line end</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line home</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line start</P>
|
||||||
|
<P VAL="PID_CmdLineHome">?line beginning</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
<RULE NAME="PID_CmdMenu" ID="PID_CmdMenu" TOPLEVEL="ACTIVE">
|
||||||
|
<L PROPNAME="PID_CmdMenu" PROPID="PID_CmdMenu">
|
||||||
|
<P VAL="PID_CmdMenuFile">file</P>
|
||||||
|
<P VAL="PID_CmdNew">new</P>
|
||||||
|
<P VAL="PID_CmdOpen">open</P>
|
||||||
|
<P VAL="PID_CmdSave">save</P>
|
||||||
|
<P VAL="PID_CmdSaveAs">save as</P>
|
||||||
|
<P VAL="PID_CmdExit">exit</P>
|
||||||
|
<P VAL="PID_CmdMenuEdit">edit</P>
|
||||||
|
<P VAL="PID_CmdCut">cut</P>
|
||||||
|
<P VAL="PID_CmdCopy">copy</P>
|
||||||
|
<P VAL="PID_CmdPaste">paste</P>
|
||||||
|
<P VAL="PID_CmdMenuVoice">voice</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">listen for dictation</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">?start dictation</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">start dictating</P>
|
||||||
|
<P VAL="PID_CmdDictationMode">end ?of command mode</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">listen for command</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">listen for commands</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">stop dictation</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">end ?of dictation</P>
|
||||||
|
<P VAL="PID_CmdCommandMode">stop dictating</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">?turn microphone off</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">?turn mike off</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">close microphone</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">microphone on</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">grammars active</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">grammars inactive</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">activate grammars</P>
|
||||||
|
<P VAL="PID_CmdMicrophone">deactivate grammars</P>
|
||||||
|
<P VAL="PID_CmdPlayback">play</P>
|
||||||
|
<P VAL="PID_CmdPlayback">play back</P>
|
||||||
|
<P VAL="PID_CmdAddDeleteWords">add ?and delete word</P>
|
||||||
|
<P VAL="PID_CmdSelectWholeWords">select whole word</P>
|
||||||
|
<P VAL="PID_CmdSelectWholeWords">select whole words</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared engine</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared recognition engine</P>
|
||||||
|
<P VAL="PID_CmdSharedRecoEngine">shared reco engine</P>
|
||||||
|
<P VAL="PID_CmdVoiceTraining">?voice training</P>
|
||||||
|
<P VAL="PID_CmdMicrophoneSetup">microphone setup</P>
|
||||||
|
<P VAL="PID_CmdMenuHelp">help</P>
|
||||||
|
<P VAL="PID_CmdAbout">about</P>
|
||||||
|
<P VAL="PID_CmdEscape">cancel</P>
|
||||||
|
<P VAL="PID_CmdEscape">escape</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<!-- Internal number rules -->
|
||||||
|
<RULE NAME="tens">
|
||||||
|
<L PROPNAME="PID_Tens" PROPID="PID_Tens">
|
||||||
|
<P VAL="20">twenty</P>
|
||||||
|
<P VAL="30">thirty</P>
|
||||||
|
<P VAL="40">forty</P>
|
||||||
|
<P VAL="50">fifty</P>
|
||||||
|
<P VAL="60">sixty</P>
|
||||||
|
<P VAL="70">seventy</P>
|
||||||
|
<P VAL="80">eighty</P>
|
||||||
|
<P VAL="90">ninety</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="ones">
|
||||||
|
<L PROPNAME="PID_Ones" PROPID="PID_Ones">
|
||||||
|
<P VAL="1">one</P>
|
||||||
|
<P VAL="2">two</P>
|
||||||
|
<P VAL="3">three</P>
|
||||||
|
<P VAL="4">four</P>
|
||||||
|
<P VAL="5">five</P>
|
||||||
|
<P VAL="6">six</P>
|
||||||
|
<P VAL="7">seven</P>
|
||||||
|
<P VAL="8">eight</P>
|
||||||
|
<P VAL="9">nine</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
<RULE NAME="onesfrag">
|
||||||
|
<L>
|
||||||
|
<P>
|
||||||
|
<RULEREF NAME="ones"/>
|
||||||
|
</P>
|
||||||
|
<L PROPNAME="PID_Ones" PROPID="PID_Ones">
|
||||||
|
<P VAL="0">zero</P>
|
||||||
|
<P VAL="10">ten</P>
|
||||||
|
<P VAL="11">eleven</P>
|
||||||
|
<P VAL="12">twelve</P>
|
||||||
|
<P VAL="13">thirteen</P>
|
||||||
|
<P VAL="14">fourteen</P>
|
||||||
|
<P VAL="15">fifteen</P>
|
||||||
|
<P VAL="16">sixteen</P>
|
||||||
|
<P VAL="17">seventeen</P>
|
||||||
|
<P VAL="18">eighteen</P>
|
||||||
|
<P VAL="19">nineteen</P>
|
||||||
|
</L>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
|
||||||
|
</GRAMMAR>
|
15
mp/src/utils/sapi51/Samples/CPP/DictPad/jpn_dictmode.xml
Normal file
15
mp/src/utils/sapi51/Samples/CPP/DictPad/jpn_dictmode.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<GRAMMAR LANGID="411">
|
||||||
|
<DEFINE>
|
||||||
|
<ID NAME="PID_DictMode" VAL="1"/>
|
||||||
|
<ID NAME="PID_DictCommand" VAL="901"/>
|
||||||
|
|
||||||
|
</DEFINE>
|
||||||
|
|
||||||
|
<RULE NAME="PID_DictMode" ID="PID_DictMode" TOPLEVEL="ACTIVE">
|
||||||
|
<L PROPNAME="PID_DictMode" PROPID="PID_DictMode">
|
||||||
|
<P VAL="PID_DictCommand">command</P>
|
||||||
|
<P VAL="PID_DictCommand">computer</P>
|
||||||
|
</L>
|
||||||
|
</RULE>
|
||||||
|
|
||||||
|
</GRAMMAR>
|
111
mp/src/utils/sapi51/Samples/CPP/DictPad/jpn_dictpad.rc
Normal file
111
mp/src/utils/sapi51/Samples/CPP/DictPad/jpn_dictpad.rc
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Menu
|
||||||
|
//
|
||||||
|
|
||||||
|
IDC_DICTPAD MENU DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
POPUP "&File"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "&New\tCtrl+N", ID_FILE_NEW
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
|
||||||
|
MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
|
||||||
|
MENUITEM "Save &As...", ID_FILE_SAVEAS
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "E&xit\tCtrl+X", IDM_EXIT
|
||||||
|
END
|
||||||
|
POPUP "&Edit"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
|
||||||
|
MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
|
||||||
|
MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
|
||||||
|
END
|
||||||
|
POPUP "&Voice"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "Listen for &Dictation", IDM_DICTATION_MODE, CHECKED
|
||||||
|
MENUITEM "Listen for &Commands", IDM_COMMAND_MODE
|
||||||
|
MENUITEM "&Grammars active\tCtrl+M", IDM_MIC_TOGGLE
|
||||||
|
MENUITEM "Play&back\tCtrl+P", IDM_PLAY
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Add/Delete Word(s)...", IDM_ADDREMOVEWORDS
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "Select &Whole Words", IDM_WHOLE_WORDS, CHECKED
|
||||||
|
MENUITEM "S&hared recognition engine", IDM_SHAREDENGINE
|
||||||
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "&Voice Training...", IDM_VOICE_TRAINING
|
||||||
|
MENUITEM "Micro&phone Setup...", IDM_MICROPHONE_SETUP
|
||||||
|
END
|
||||||
|
POPUP "&Help"
|
||||||
|
BEGIN
|
||||||
|
MENUITEM "&About ...", IDM_ABOUT
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Accelerator
|
||||||
|
//
|
||||||
|
|
||||||
|
IDC_DICTPAD ACCELERATORS MOVEABLE PURE
|
||||||
|
BEGIN
|
||||||
|
"/", IDM_ABOUT, ASCII, ALT, NOINVERT
|
||||||
|
"?", IDM_ABOUT, ASCII, ALT, NOINVERT
|
||||||
|
"C", IDM_COMMAND_MODE, VIRTKEY, ALT, NOINVERT
|
||||||
|
"D", IDM_DICTATION_MODE, VIRTKEY, ALT, NOINVERT
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Dialog
|
||||||
|
//
|
||||||
|
|
||||||
|
IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 62
|
||||||
|
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION "About"
|
||||||
|
FONT 8, "System"
|
||||||
|
BEGIN
|
||||||
|
ICON IDI_DICTPAD,IDC_MYICON,14,9,20,20
|
||||||
|
LTEXT "DictPad ",IDC_STATIC,49,10,58,8,SS_NOPREFIX
|
||||||
|
LTEXT "(c) 2001 Microsoft Corporation.",IDC_STATIC,49,23,177,
|
||||||
|
11
|
||||||
|
DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
|
||||||
|
LTEXT "All rights reserved.",IDC_STATIC,49,39,177,11
|
||||||
|
END
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SRGRAMMAR
|
||||||
|
//
|
||||||
|
|
||||||
|
IDR_COMMAND_MODE_CFG SRGRAMMAR DISCARDABLE "jpn_cmdmode.cfg"
|
||||||
|
IDR_DICTATION_MODE_CFG SRGRAMMAR DISCARDABLE "jpn_dictmode.cfg"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// String Table
|
||||||
|
//
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_APP_TITLE "dictpad"
|
||||||
|
IDC_DICTPAD "DICTPAD"
|
||||||
|
IDM_PLAY "Play"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDM_FONT "Allow selection of a different font "
|
||||||
|
IDM_DICTATION_MODE "Dictation"
|
||||||
|
IDS_ADD "Add"
|
||||||
|
IDS_CHANGE "Change"
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDM_MIC_TOGGLE "Grammars active/inactive"
|
||||||
|
END
|
||||||
|
|
548
mp/src/utils/sapi51/Samples/CPP/DictPad/phrasereplace.cpp
Normal file
548
mp/src/utils/sapi51/Samples/CPP/DictPad/phrasereplace.cpp
Normal file
@ -0,0 +1,548 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* phrasereplace.cpp
|
||||||
|
* Implementation details for the CPhraseReplacement object which
|
||||||
|
* does the bookkeeping to translate between a phrase as
|
||||||
|
* displayed with ITN replacements and a phrase as seen
|
||||||
|
* by the associated RecoResult.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "phrasereplace.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* CPhraseReplacement::CPhraseReplacement *
|
||||||
|
*----------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Constructor for the CPhraseReplacement class
|
||||||
|
*******************************************************************************/
|
||||||
|
CPhraseReplacement::CPhraseReplacement() : m_fUseMaps( false ),
|
||||||
|
m_fSuccessfulSetup( false ),
|
||||||
|
m_pPhrase( NULL ),
|
||||||
|
m_cReplacementElements( 0 ),
|
||||||
|
m_pulPreToPostTable( NULL ),
|
||||||
|
m_pulPostToPreTable( NULL ),
|
||||||
|
m_pulPostToReplacementTable( NULL )
|
||||||
|
{} /* CPhraseReplacement::CPhraseReplacement */
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* CPhraseReplacement::~CPhraseReplacement *
|
||||||
|
*-----------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Destructor for the CPhraseReplacement class
|
||||||
|
* Deletes the tables and frees the SPPHRASE.
|
||||||
|
*******************************************************************************/
|
||||||
|
CPhraseReplacement::~CPhraseReplacement()
|
||||||
|
{
|
||||||
|
// If memory was allocated for these, then free
|
||||||
|
delete[] m_pulPreToPostTable;
|
||||||
|
delete[] m_pulPostToPreTable;
|
||||||
|
delete[] m_pulPostToReplacementTable;
|
||||||
|
|
||||||
|
if ( m_pPhrase )
|
||||||
|
{
|
||||||
|
// The SPPHRASE was CoTaskMemAlloc()ed by CPhraseReplacement::Initialize()
|
||||||
|
// so it needs to be freed
|
||||||
|
::CoTaskMemFree( m_pPhrase );
|
||||||
|
}
|
||||||
|
} /* CPhraseRepalcement::~CPhraseReplacement */
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* CPhraseReplacement::Initialize *
|
||||||
|
*--------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Gets the phrase from the ISpPhrase object and calls SetUpMaps().
|
||||||
|
* This initialization routine can be called either from a
|
||||||
|
* client with a new CPhraseReplacement object or
|
||||||
|
* when an alternate is committed (or the recoresult has
|
||||||
|
* otherwise changed).
|
||||||
|
* Return:
|
||||||
|
* Return value of ISpRecoResult::GetPhrase()
|
||||||
|
* Return value of CPhraseReplacement::SetUpMaps()
|
||||||
|
*******************************************************************************/
|
||||||
|
HRESULT CPhraseReplacement::Initialize( ISpPhrase &rPhrase )
|
||||||
|
{
|
||||||
|
// Get (or re-get) the phrase
|
||||||
|
if ( m_pPhrase )
|
||||||
|
{
|
||||||
|
::CoTaskMemFree( m_pPhrase );
|
||||||
|
}
|
||||||
|
HRESULT hr = rPhrase.GetPhrase( &m_pPhrase );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = SetUpMaps();
|
||||||
|
m_fSuccessfulSetup = SUCCEEDED( hr );
|
||||||
|
m_fUseMaps = (S_OK == hr);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
} /* CPhraseReplacement::Initialize */
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* CPhraseReplacement::SetUpMaps *
|
||||||
|
*-------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Initializes the various maps in the CPhraseReplacement object.
|
||||||
|
* Called from within the initialization routines.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* S_FALSE if no maps necessary
|
||||||
|
* E_OUTOFMEMORY
|
||||||
|
*******************************************************************************/
|
||||||
|
HRESULT CPhraseReplacement::SetUpMaps()
|
||||||
|
{
|
||||||
|
_ASSERTE( m_pPhrase );
|
||||||
|
if ( !m_pPhrase )
|
||||||
|
{
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !m_pPhrase->cReplacements )
|
||||||
|
{
|
||||||
|
// No phrase replacements; nothing needs to be done for this phrase
|
||||||
|
m_cReplacementElements = m_pPhrase->Rule.ulCountOfElements;
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary place to keep replacement info:
|
||||||
|
// This array will indicate which elements in the original (non-replaced)
|
||||||
|
// phrase start off a replacement.
|
||||||
|
// For instance, in the phrase "I have three dollars", pulPreToReplacementTable[2]
|
||||||
|
// would indicate that "three" starts off a replacement; there is one replacement
|
||||||
|
// ($3), so pulPreToReplacementTable[2] would have the value 0.
|
||||||
|
ULONG *pulPreToReplacementTable =
|
||||||
|
new ULONG[ m_pPhrase->Rule.ulCountOfElements ];
|
||||||
|
if ( !pulPreToReplacementTable )
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the value to that will indicate that no replacement starts with this element:
|
||||||
|
// Since there are m_pPhrase->cReplacements replacements,
|
||||||
|
// no replacement is going to have the index m_pPhrase->cReplacements
|
||||||
|
m_ulNoReplacementValue = m_pPhrase->cReplacements;
|
||||||
|
|
||||||
|
// Initialize this array to indicate that no elements kick off replacements
|
||||||
|
for ( ULONG ul = 0; ul < m_pPhrase->Rule.ulCountOfElements; ul++ )
|
||||||
|
{
|
||||||
|
pulPreToReplacementTable[ul] = m_ulNoReplacementValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in the temporary array that maps pre-replacement elements to the
|
||||||
|
// replacements they start (if any).
|
||||||
|
// Count up the number of elements that get replaced.
|
||||||
|
ULONG cReplacedElements = 0;
|
||||||
|
for ( ULONG ulReplacement = 0;
|
||||||
|
ulReplacement < m_pPhrase->cReplacements;
|
||||||
|
ulReplacement++ )
|
||||||
|
{
|
||||||
|
// Record the replacement's index in the ulFirstElement'th position in the
|
||||||
|
// temporary array
|
||||||
|
pulPreToReplacementTable[(m_pPhrase->pReplacements[ulReplacement]).ulFirstElement]
|
||||||
|
= ulReplacement;
|
||||||
|
|
||||||
|
// Bump the number of replaced elements
|
||||||
|
cReplacedElements +=
|
||||||
|
(m_pPhrase->pReplacements[ulReplacement]).ulCountOfElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate how many phrase elements there will be after replacement.
|
||||||
|
// Note that each replacement will be counted as only one element ("$3" is
|
||||||
|
// one element, as is "June 28, 1977")
|
||||||
|
m_cReplacementElements = m_pPhrase->Rule.ulCountOfElements
|
||||||
|
+ m_pPhrase->cReplacements - cReplacedElements ;
|
||||||
|
|
||||||
|
// Allocate the appropriate amount of space for the tables.
|
||||||
|
// Note that a CPhraseReplace object may be initialized more than once
|
||||||
|
// in its lifetime, so we may need to free up memory previously
|
||||||
|
// allocated for these tables.
|
||||||
|
delete[] m_pulPreToPostTable;
|
||||||
|
delete[] m_pulPostToPreTable;
|
||||||
|
delete[] m_pulPostToReplacementTable;
|
||||||
|
|
||||||
|
// This table maps from pre-replacement elements to post-replacement elements
|
||||||
|
// There are ulCountOfElements elements in the pre-replacement phrase
|
||||||
|
m_pulPreToPostTable = new ULONG[ m_pPhrase->Rule.ulCountOfElements ];
|
||||||
|
|
||||||
|
// This table maps from post-replacement elements to pre-replacement elements
|
||||||
|
// There are m_cReplacementElements elements in the post-replacement phrase
|
||||||
|
m_pulPostToPreTable = new ULONG[ m_cReplacementElements ];
|
||||||
|
|
||||||
|
// This table maps from post-replacement elements to the replacement (if any)
|
||||||
|
// to which they correspond.
|
||||||
|
m_pulPostToReplacementTable = new ULONG[ m_cReplacementElements];
|
||||||
|
|
||||||
|
// Check to make sure we haven't run into any memory issues
|
||||||
|
if ( !m_pulPreToPostTable || !m_pulPostToPreTable || !m_pulPostToReplacementTable )
|
||||||
|
{
|
||||||
|
delete[] pulPreToReplacementTable;
|
||||||
|
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in the tables.
|
||||||
|
// There will be two counters
|
||||||
|
// ulPreReplElement which walks through the elements of the original phrase;
|
||||||
|
// ulPostReplElement which walks through the elements of the post-replacement phrase.
|
||||||
|
// Usually with replacements, a post-replacement elements ($3) corresponds to more
|
||||||
|
// than one pre-replacement element ("three dollars")
|
||||||
|
ULONG ulPreReplElement = 0;
|
||||||
|
for ( ULONG ulPostReplElement = 0;
|
||||||
|
ulPostReplElement < m_cReplacementElements;
|
||||||
|
ulPostReplElement++ )
|
||||||
|
{
|
||||||
|
// Right now, ulPreReplElement and upPostReplElement are referring to the
|
||||||
|
// same element (though they may have different values, of course)
|
||||||
|
m_pulPostToPreTable[ulPostReplElement] = ulPreReplElement;
|
||||||
|
m_pulPostToReplacementTable[ulPostReplElement] =
|
||||||
|
pulPreToReplacementTable[ulPreReplElement];
|
||||||
|
|
||||||
|
if ( m_pulPostToReplacementTable[ulPostReplElement] < m_ulNoReplacementValue )
|
||||||
|
{
|
||||||
|
// This is a replaced element; so several of the pre-replacement
|
||||||
|
// elements will correspond to this post-replacement element.
|
||||||
|
|
||||||
|
// Use the element-to-replacement info to determine which one, so that
|
||||||
|
// we know how many pre-replacement elements to grab.
|
||||||
|
const SPPHRASEREPLACEMENT *pRepl = m_pPhrase->pReplacements +
|
||||||
|
m_pulPostToReplacementTable[ulPostReplElement];
|
||||||
|
|
||||||
|
// For each element covered by the replacement, make another pre-replacement
|
||||||
|
// element map to this post-replacement element and increment
|
||||||
|
// ulPreReplElement.
|
||||||
|
// (i.e. both "three" and "dollars" would map to "$3")
|
||||||
|
for ( ULONG ul = 0; ul < pRepl->ulCountOfElements; ul++, ulPreReplElement++ )
|
||||||
|
{
|
||||||
|
_ASSERTE( ulPreReplElement < m_pPhrase->Rule.ulCountOfElements );
|
||||||
|
m_pulPreToPostTable[ulPreReplElement] = ulPostReplElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is not a replaced element, so there is a 1-1 relationship
|
||||||
|
// between it and the ulPreReplElement'th pre-replacement element
|
||||||
|
_ASSERTE( ulPreReplElement < m_pPhrase->Rule.ulCountOfElements );
|
||||||
|
m_pulPreToPostTable[ulPreReplElement++] = ulPostReplElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free up temporary array
|
||||||
|
delete[] pulPreToReplacementTable;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CPhraseReplacement::SetUpMaps */
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* CPhraseReplacement::GetNumNoReplacementElements *
|
||||||
|
*-------------------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Gets the number of elements as seen from the recoresult's point of view
|
||||||
|
* (i.e., without replacement)
|
||||||
|
**********************************************************************************/
|
||||||
|
ULONG CPhraseReplacement::GetNumNoReplacementElements()
|
||||||
|
{
|
||||||
|
if ( !m_fSuccessfulSetup )
|
||||||
|
{
|
||||||
|
_ASSERTE( false );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_pPhrase->Rule.ulCountOfElements;
|
||||||
|
} /* CPhraseReplacement::GetNumReplacementElements */
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* CPhraseReplacement::GetNumReplacementElements *
|
||||||
|
*-----------------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Gets the number of elements as seen from the caller's point of view
|
||||||
|
* (i.e., with replacement)
|
||||||
|
**********************************************************************************/
|
||||||
|
ULONG CPhraseReplacement::GetNumReplacementElements()
|
||||||
|
{
|
||||||
|
if ( !m_fSuccessfulSetup )
|
||||||
|
{
|
||||||
|
_ASSERTE( false );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_fUseMaps )
|
||||||
|
{
|
||||||
|
// There are replacements
|
||||||
|
return m_cReplacementElements;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There are no replacements
|
||||||
|
return m_pPhrase->Rule.ulCountOfElements;
|
||||||
|
}
|
||||||
|
} /* CPhraseReplacement::GetNumReplacementElements */
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* CPhraseReplacement::GetDisplayText *
|
||||||
|
*------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Hands back the text associated with the given phrase "element"
|
||||||
|
* If bUseReplacedElements is false or this phrase has no replacements,
|
||||||
|
* simply returns the display text for the appropriate element.
|
||||||
|
* Otherwise, consults the element mappings and returns the
|
||||||
|
* replacement text or the display text for the ulElement'th pre-
|
||||||
|
* replacement element, as appropriate.
|
||||||
|
* Return:
|
||||||
|
* Pointer to a text buffer containing the display text
|
||||||
|
* NULL if failed
|
||||||
|
**********************************************************************************/
|
||||||
|
const WCHAR * CPhraseReplacement::GetDisplayText( ULONG ulElement,
|
||||||
|
BYTE *pbDisplayAttributes,
|
||||||
|
bool bUseReplacedElements )
|
||||||
|
{
|
||||||
|
if ( !m_fSuccessfulSetup )
|
||||||
|
{
|
||||||
|
_ASSERTE( false );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WCHAR *pwszRetText = NULL;
|
||||||
|
BYTE bDisplayAttributes = 0;
|
||||||
|
|
||||||
|
if ( !m_fUseMaps || !bUseReplacedElements )
|
||||||
|
{
|
||||||
|
// Do not map; just hand back the display text for the requested
|
||||||
|
// element
|
||||||
|
if ( ulElement < m_pPhrase->Rule.ulCountOfElements )
|
||||||
|
{
|
||||||
|
bDisplayAttributes =
|
||||||
|
m_pPhrase->pElements[ulElement].bDisplayAttributes;
|
||||||
|
pwszRetText = m_pPhrase->pElements[ulElement].pszDisplayText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Caller is using a post-replacement index and wants the text from that
|
||||||
|
// replacement
|
||||||
|
if ( ulElement < m_cReplacementElements )
|
||||||
|
{
|
||||||
|
if ( m_pulPostToReplacementTable[ulElement] < m_pPhrase->cReplacements )
|
||||||
|
{
|
||||||
|
// This is a replaced element; hand back the replacement text
|
||||||
|
// and attributes
|
||||||
|
const SPPHRASEREPLACEMENT *pRepl = m_pPhrase->pReplacements +
|
||||||
|
m_pulPostToReplacementTable[ulElement];
|
||||||
|
pwszRetText = pRepl->pszReplacementText;
|
||||||
|
bDisplayAttributes = pRepl->bDisplayAttributes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This element has not been replaced; hand back the text
|
||||||
|
// and attributes corresponding to the appropriate
|
||||||
|
// pre-replacement element
|
||||||
|
ULONG ulPreReplElement = m_pulPostToPreTable[ulElement];
|
||||||
|
pwszRetText = m_pPhrase->pElements[ulPreReplElement].pszDisplayText;
|
||||||
|
bDisplayAttributes =
|
||||||
|
m_pPhrase->pElements[ulPreReplElement].bDisplayAttributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pbDisplayAttributes )
|
||||||
|
{
|
||||||
|
*pbDisplayAttributes = bDisplayAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case of error, this remains NULL
|
||||||
|
return pwszRetText;
|
||||||
|
|
||||||
|
} /* CPhraseReplacement::GetDisplayText */
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* CPhraseReplacement::PreToPostReplacementIndex *
|
||||||
|
*-----------------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Converts from a pre-replacement index to a with-replacement index.
|
||||||
|
* If ulSPPHRASEIndex is equal to the number of (pre-replacement) elements
|
||||||
|
* will return the number of post-replacement elements in
|
||||||
|
* *pulReplacedPhraseIndex
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_POINTER
|
||||||
|
* E_FAIL
|
||||||
|
* E_INVALIDARG if ulSPPHRASEIndex is out-of-bounds
|
||||||
|
**********************************************************************************/
|
||||||
|
HRESULT CPhraseReplacement::PreToPostReplacementIndex( ULONG ulSPPHRASEIndex,
|
||||||
|
ULONG *pulReplacedPhraseIndex)
|
||||||
|
{
|
||||||
|
if ( !m_fSuccessfulSetup )
|
||||||
|
{
|
||||||
|
_ASSERTE( false );
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !pulReplacedPhraseIndex )
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
if ( ulSPPHRASEIndex > m_pPhrase->Rule.ulCountOfElements )
|
||||||
|
{
|
||||||
|
// Out of bounds index
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ulSPPHRASEIndex == m_pPhrase->Rule.ulCountOfElements )
|
||||||
|
{
|
||||||
|
*pulReplacedPhraseIndex = m_fUseMaps ?
|
||||||
|
m_cReplacementElements : m_pPhrase->Rule.ulCountOfElements;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the maps are valid, do a lookup;
|
||||||
|
// otherwise just return the original index
|
||||||
|
*pulReplacedPhraseIndex = m_fUseMaps ?
|
||||||
|
m_pulPreToPostTable[ulSPPHRASEIndex] : ulSPPHRASEIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CPhraseReplacement::PreToPostReplacementIndex */
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* CPhraseReplacement::PostToPreReplacementIndex *
|
||||||
|
*-----------------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Converts from a with-replacement index to a pre-replacement index
|
||||||
|
* If ulReplacedPhraseIndex is equal to the number of (post-replacement)
|
||||||
|
* elements, will return the number of pre-replacement elements in
|
||||||
|
* *pulSPPHRASEIndex
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_POINTER
|
||||||
|
* E_FAIL
|
||||||
|
* E_INVALIDARG if ulReplacedPhraseIndex is out-of-bounds
|
||||||
|
**********************************************************************************/
|
||||||
|
HRESULT CPhraseReplacement::PostToPreReplacementIndex( ULONG ulReplacedPhraseIndex,
|
||||||
|
ULONG *pulSPPHRASEIndex )
|
||||||
|
{
|
||||||
|
if ( !m_fSuccessfulSetup )
|
||||||
|
{
|
||||||
|
_ASSERTE( false );
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !pulSPPHRASEIndex )
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
if ( ulReplacedPhraseIndex > m_cReplacementElements )
|
||||||
|
{
|
||||||
|
// Out of bounds index
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ulReplacedPhraseIndex == m_cReplacementElements )
|
||||||
|
{
|
||||||
|
*pulSPPHRASEIndex = m_pPhrase->Rule.ulCountOfElements;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the maps are valid, do a lookup;
|
||||||
|
//otherwise just return the original index
|
||||||
|
*pulSPPHRASEIndex = m_fUseMaps ?
|
||||||
|
m_pulPostToPreTable[ulReplacedPhraseIndex] : ulReplacedPhraseIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CPhraseReplacement::PostToPreReplacementIndex */
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* CPhraseReplacement::ExpandToIncludeWholeReplacements *
|
||||||
|
*------------------------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Takes pre-replacement indices in the in/out params pulPreReplStart and
|
||||||
|
* pcPreReplElts and expands them, if necessary, to contain entire
|
||||||
|
* replacements.
|
||||||
|
* Example: "Thirty nine is the first uninteresting number."
|
||||||
|
* If *pulPreReplStart = 1 and *pcPreReplElts = 4, then when this
|
||||||
|
* function returns *pulPreReplStart = 0 and *pcPreReplElts = 5 (in order
|
||||||
|
* to include "thirty" at the beginning)
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_POINTER
|
||||||
|
* E_INVALIDARG if *pulPreReplStart and *pcPreReplElts indicate an
|
||||||
|
* out-of-bounds range or if *pcPreReplElts is 0
|
||||||
|
**********************************************************************************/
|
||||||
|
HRESULT CPhraseReplacement::ExpandToIncludeWholeReplacements( ULONG *pulPreReplStart,
|
||||||
|
ULONG *pcPreReplElts )
|
||||||
|
{
|
||||||
|
if ( !m_fSuccessfulSetup )
|
||||||
|
{
|
||||||
|
_ASSERTE( false );
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !pulPreReplStart || !pcPreReplElts )
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !m_fUseMaps )
|
||||||
|
{
|
||||||
|
// Don't need to do anything since there are no maps
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate params
|
||||||
|
if ( (*pulPreReplStart >= GetNumNoReplacementElements()) ||
|
||||||
|
(0 == *pcPreReplElts) ||
|
||||||
|
((*pulPreReplStart + *pcPreReplElts) > GetNumNoReplacementElements()) )
|
||||||
|
{
|
||||||
|
// Out-of-bounds range or degenerate element range
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the start to a post-replacement value and see if that
|
||||||
|
// element has any replacement associated with it
|
||||||
|
ULONG ulPostReplStart;
|
||||||
|
HRESULT hr = PreToPostReplacementIndex( *pulPreReplStart, &ulPostReplStart );
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
ULONG ulReplacement = m_pulPostToReplacementTable[ ulPostReplStart ];
|
||||||
|
if ( ulReplacement < m_ulNoReplacementValue )
|
||||||
|
{
|
||||||
|
// There is an associated replacement
|
||||||
|
// Move back *pulPreReplStart to the beginning of what that replacement replaces
|
||||||
|
const SPPHRASEREPLACEMENT *pRepl = m_pPhrase->pReplacements + ulReplacement;
|
||||||
|
*pulPreReplStart = pRepl->ulFirstElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the same for the last element
|
||||||
|
ULONG ulPreReplLast = *pulPreReplStart + *pcPreReplElts - 1;
|
||||||
|
ULONG ulPostReplLast;
|
||||||
|
hr = PreToPostReplacementIndex( ulPreReplLast, &ulPostReplLast );
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
ULONG ulReplacement = m_pulPostToReplacementTable[ ulPostReplLast ];
|
||||||
|
if ( ulReplacement < m_ulNoReplacementValue )
|
||||||
|
{
|
||||||
|
// There is an associated replacement
|
||||||
|
// Advance ulPreReplLast to the last element that the replacement replaces
|
||||||
|
const SPPHRASEREPLACEMENT *pRepl = m_pPhrase->pReplacements + ulReplacement;
|
||||||
|
ulPreReplLast = pRepl->ulFirstElement + pRepl->ulCountOfElements - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the count of elements
|
||||||
|
*pcPreReplElts = ulPreReplLast - *pulPreReplStart + 1;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CPhraseReplacement::ExpandToIncludeWholeReplacements */
|
61
mp/src/utils/sapi51/Samples/CPP/DictPad/phrasereplace.h
Normal file
61
mp/src/utils/sapi51/Samples/CPP/DictPad/phrasereplace.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* phrasereplace.h
|
||||||
|
* This module contains the definition support for CPhraseReplacement,
|
||||||
|
* which does the bookkeeping to translate between a phrase as
|
||||||
|
* displayed with ITN replacements and a phrase as thought of
|
||||||
|
* by the associated RecoResult
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __PHRASEREPLACE_H
|
||||||
|
#define __PHRASEREPLACE_H
|
||||||
|
|
||||||
|
class CPhraseReplacement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CPhraseReplacement();
|
||||||
|
~CPhraseReplacement();
|
||||||
|
|
||||||
|
HRESULT Initialize( ISpPhrase &rSpPhrase );
|
||||||
|
|
||||||
|
ULONG GetNumNoReplacementElements();
|
||||||
|
ULONG GetNumReplacementElements();
|
||||||
|
|
||||||
|
// Gets the text of a given element
|
||||||
|
const WCHAR * GetDisplayText( ULONG ulElement,
|
||||||
|
BYTE *pbDisplayAttributes = NULL,
|
||||||
|
bool bUseReplacedElements = true );
|
||||||
|
|
||||||
|
// Conversion methods
|
||||||
|
HRESULT PreToPostReplacementIndex( ULONG ulSPPHRASEIndex,
|
||||||
|
ULONG *pulReplacePhraseIndex );
|
||||||
|
HRESULT PostToPreReplacementIndex( ULONG ulReplacedPhraseIndex,
|
||||||
|
ULONG *pulSPPHRASEIndex );
|
||||||
|
HRESULT ExpandToIncludeWholeReplacements( ULONG *pulPreReplStart,
|
||||||
|
ULONG *pcPreReplElts );
|
||||||
|
|
||||||
|
private:
|
||||||
|
HRESULT SetUpMaps(); // Does the real initialization work
|
||||||
|
|
||||||
|
bool m_fUseMaps; // Indicates whether to use the maps
|
||||||
|
bool m_fSuccessfulSetup; // Indicates the this object is usable
|
||||||
|
|
||||||
|
SPPHRASE *m_pPhrase;
|
||||||
|
ULONG m_cReplacementElements; // Number of elements after
|
||||||
|
// replacements have been made
|
||||||
|
ULONG *m_pulPreToPostTable; // Given the index of an element in the phrase,
|
||||||
|
// contains the index of that element with
|
||||||
|
// replacements
|
||||||
|
ULONG *m_pulPostToPreTable; // Given the index of an element with replacements,
|
||||||
|
// contains the index of that element in the
|
||||||
|
// original phrase
|
||||||
|
ULONG *m_pulPostToReplacementTable; // Given the index of an element with replacements,
|
||||||
|
// indicates which replacement (if any) that
|
||||||
|
// element corresponds to
|
||||||
|
ULONG m_ulNoReplacementValue; // Value in tables to indicate that no
|
||||||
|
// replacement corresponds to this element.
|
||||||
|
}; // class CPhraseReplacement
|
||||||
|
|
||||||
|
#endif // __PHRASEREPLACE_H
|
56
mp/src/utils/sapi51/Samples/CPP/DictPad/readme.txt
Normal file
56
mp/src/utils/sapi51/Samples/CPP/DictPad/readme.txt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
========================================================================
|
||||||
|
WIN32 APPLICATION : dictpad
|
||||||
|
========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
AppWizard has created this dictpad application for you.
|
||||||
|
|
||||||
|
This file contains a summary of what you will find in each of the files that
|
||||||
|
make up your dictpad application.
|
||||||
|
|
||||||
|
dictpad.cpp
|
||||||
|
This is the main application source file.
|
||||||
|
|
||||||
|
dictpad.dsp
|
||||||
|
This file (the project file) contains information at the project level and
|
||||||
|
is used to build a single project or subproject. Other users can share the
|
||||||
|
project (.dsp) file, but they should export the makefiles locally.
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
AppWizard has created the following resources:
|
||||||
|
|
||||||
|
dictpad.rc
|
||||||
|
This is a listing of all of the Microsoft Windows resources that the
|
||||||
|
program uses. It includes the icons, bitmaps, and cursors that are stored
|
||||||
|
in the RES subdirectory. This file can be directly edited in Microsoft
|
||||||
|
Visual C++.
|
||||||
|
|
||||||
|
res\dictpad.ico
|
||||||
|
This is an icon file, which is used as the application's icon (32x32).
|
||||||
|
This icon is included by the main resource file dictpad.rc.
|
||||||
|
|
||||||
|
small.ico
|
||||||
|
%%This is an icon file, which contains a smaller version (16x16)
|
||||||
|
of the application's icon. This icon is included by the main resource
|
||||||
|
file dictpad.rc.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
Other standard files:
|
||||||
|
|
||||||
|
StdAfx.h, StdAfx.cpp
|
||||||
|
These files are used to build a precompiled header (PCH) file
|
||||||
|
named dictpad.pch and a precompiled types file named StdAfx.obj.
|
||||||
|
|
||||||
|
Resource.h
|
||||||
|
This is the standard header file, which defines new resource IDs.
|
||||||
|
Microsoft Visual C++ reads and updates this file.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
Other notes:
|
||||||
|
|
||||||
|
AppWizard uses "TODO:" to indicate parts of the source code you
|
||||||
|
should add to or customize.
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
546
mp/src/utils/sapi51/Samples/CPP/DictPad/recomgr.cpp
Normal file
546
mp/src/utils/sapi51/Samples/CPP/DictPad/recomgr.cpp
Normal file
@ -0,0 +1,546 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* recomgr.cpp
|
||||||
|
* Support for queuing insertion points and correctly placing
|
||||||
|
* recognized text
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include <richedit.h>
|
||||||
|
#include "recomgr.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::CRecoEventMgr *
|
||||||
|
*------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Constructor for the recoevent manager
|
||||||
|
*****************************************************************************/
|
||||||
|
CRecoEventMgr::CRecoEventMgr( HINSTANCE hInstance ) :
|
||||||
|
m_hInst( hInstance ),
|
||||||
|
m_fPhraseStarted( false ),
|
||||||
|
m_pTextSel( NULL ),
|
||||||
|
m_pHeadLP( NULL ),
|
||||||
|
m_pHeadWM( NULL ),
|
||||||
|
m_pTailWM( NULL )
|
||||||
|
{
|
||||||
|
} /* CRecoEventMgr::CRecoEventMgr */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::~CRecoEventMgr *
|
||||||
|
*-------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Destructor for the recoevent manager
|
||||||
|
*****************************************************************************/
|
||||||
|
CRecoEventMgr::~CRecoEventMgr()
|
||||||
|
{
|
||||||
|
CleanUp();
|
||||||
|
} /* CRecoEventMgr::~CRecoEventMgr */
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::PhraseStart *
|
||||||
|
*----------------------------*
|
||||||
|
* Description:
|
||||||
|
* Sets the flag to indicate that a phrase has been started.
|
||||||
|
* Drops a listen point by calling SelNotify()
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_OUTOFMEMORY
|
||||||
|
* Return value of CRecoEventMgr::SelNotify()
|
||||||
|
*****************************************************************************/
|
||||||
|
HRESULT CRecoEventMgr::PhraseStart( ITextRange &rSelRange )
|
||||||
|
{
|
||||||
|
// There should not be any phrases in progress or any listen points
|
||||||
|
_ASSERTE( !m_fPhraseStarted && !m_pHeadLP );
|
||||||
|
m_fPhraseStarted = true;
|
||||||
|
|
||||||
|
// Should add a listening point right now
|
||||||
|
HRESULT hr = SelNotify( rSelRange );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !m_pHeadLP )
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pHeadLP->fFromPhraseStart = true;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CRecoEventMgr::PhraseStart */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::SelNotify *
|
||||||
|
*--------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called whenever the selection changes.
|
||||||
|
* Drops a new listening point onto the list of listening points for
|
||||||
|
* this phrase if there is a phrase currently being processed
|
||||||
|
* being listened to.
|
||||||
|
* Hands back the range to be eventually replaced by recognized
|
||||||
|
* text (or deleted).
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* S_FALSE if nothing had to be done
|
||||||
|
* E_OUTOFMEMORY
|
||||||
|
* Return value of ITextRange::GetDuplicate()
|
||||||
|
* Return value of ITextRange::Collapse()
|
||||||
|
*****************************************************************************/
|
||||||
|
HRESULT CRecoEventMgr::SelNotify( ITextRange &rSelRange )
|
||||||
|
{
|
||||||
|
// Only want to queue this listen if we are listening to a phrase
|
||||||
|
HRESULT hr = S_FALSE;
|
||||||
|
if ( m_fPhraseStarted )
|
||||||
|
{
|
||||||
|
// Get the time now
|
||||||
|
FILETIME ftNow;
|
||||||
|
::CoFileTimeNow( &ftNow );
|
||||||
|
|
||||||
|
// Does this range overlap any of the existing ranges in the list?
|
||||||
|
LISTENPOINT *p;
|
||||||
|
for ( p = m_pHeadLP;
|
||||||
|
p && AreDisjointRanges( &rSelRange, p->cpRangeToReplace );
|
||||||
|
p = p->pNext )
|
||||||
|
;
|
||||||
|
|
||||||
|
// If p is not NULL, that means that there is already some listen point
|
||||||
|
// that is adjacent to or overlaps this range, so another listen point
|
||||||
|
// is not necessary
|
||||||
|
if ( !p )
|
||||||
|
{
|
||||||
|
// Add a new listen point
|
||||||
|
LISTENPOINT *pNewPoint = new LISTENPOINT;
|
||||||
|
if ( !pNewPoint )
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the ranges
|
||||||
|
hr = rSelRange.GetDuplicate( &(pNewPoint->cpRangeToReplace) );
|
||||||
|
|
||||||
|
// Get the timestamp
|
||||||
|
pNewPoint->ftTime = ftNow;
|
||||||
|
|
||||||
|
// This flag will be set by PhraseStart() if appropriate
|
||||||
|
pNewPoint->fFromPhraseStart = false;
|
||||||
|
|
||||||
|
// No hypothesis text here yet
|
||||||
|
pNewPoint->fHasHypothesisText = false;
|
||||||
|
|
||||||
|
// Put this new listenpoint onto the head of the list
|
||||||
|
pNewPoint->pNext = m_pHeadLP;
|
||||||
|
m_pHeadLP = pNewPoint;
|
||||||
|
|
||||||
|
long lEndOfRangeToReplace;
|
||||||
|
pNewPoint->cpRangeToReplace->GetEnd( &lEndOfRangeToReplace );
|
||||||
|
|
||||||
|
// The selection should be forced to the end of the range to replace;
|
||||||
|
// this keeps the selection out of ranges that might be replaced
|
||||||
|
// by recognized text
|
||||||
|
m_pTextSel->SetRange(
|
||||||
|
lEndOfRangeToReplace, lEndOfRangeToReplace );
|
||||||
|
|
||||||
|
// If we got here, we were successful
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
} /* CRecoEventMgr::SelNotify */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::IsEditable *
|
||||||
|
*---------------------------*
|
||||||
|
* Description:
|
||||||
|
* Determines whether pRange overlaps any of the current listen points.
|
||||||
|
* If it does, and if pNextEditableRange is non-NULL, sets
|
||||||
|
* pNextEditableRange to the next range that can be edited with
|
||||||
|
* impunity
|
||||||
|
* Return:
|
||||||
|
* true iff the RecoEventMgr is okay with this text being edited
|
||||||
|
*****************************************************************************/
|
||||||
|
bool CRecoEventMgr::IsEditable( ITextRange *pRange,
|
||||||
|
ITextRange **ppNextEditableRange )
|
||||||
|
{
|
||||||
|
if ( !pRange )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !m_fPhraseStarted )
|
||||||
|
{
|
||||||
|
// Always editable if there's no reco computation
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does this range overlap or abut any of the existing ranges in the list?
|
||||||
|
LISTENPOINT *p;
|
||||||
|
for ( p = m_pHeadLP;
|
||||||
|
p && AreDisjointRanges( pRange, p->cpRangeToReplace );
|
||||||
|
p = p->pNext )
|
||||||
|
;
|
||||||
|
|
||||||
|
if ( p )
|
||||||
|
{
|
||||||
|
// There is a phrase that overlaps or abuts this one.
|
||||||
|
// If pRange dovetails onto the end of it, then the
|
||||||
|
// range is editable; otherwise it is not
|
||||||
|
long lRangeStart = 0;
|
||||||
|
long lLPEnd = 0;
|
||||||
|
pRange->GetStart( &lRangeStart );
|
||||||
|
p->cpRangeToReplace->GetEnd( &lLPEnd );
|
||||||
|
|
||||||
|
if ( lRangeStart < lLPEnd )
|
||||||
|
{
|
||||||
|
// If pNextEditableRange is non-NULL, set it a degenerate range
|
||||||
|
// at the end of the listen point range
|
||||||
|
if ( ppNextEditableRange )
|
||||||
|
{
|
||||||
|
// Release whatever is already there
|
||||||
|
if ( *ppNextEditableRange )
|
||||||
|
{
|
||||||
|
(*ppNextEditableRange)->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a duplicate of the range to replace and collapse at the end
|
||||||
|
HRESULT hr = p->cpRangeToReplace->GetDuplicate( ppNextEditableRange );
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
(*ppNextEditableRange)->Collapse( tomEnd );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppNextEditableRange = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pRange is editable
|
||||||
|
// Leave ppNextEditableRange, whatever it is
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} /* CRecoEventMgr::IsEditable */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::QueueCommand *
|
||||||
|
*-----------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called when the engine is currently processing a phrase.
|
||||||
|
* Puts the command at the tail of the command queue.
|
||||||
|
*****************************************************************************/
|
||||||
|
void CRecoEventMgr::QueueCommand( HWND hWnd, UINT message,
|
||||||
|
WPARAM wParam, LPARAM lParam )
|
||||||
|
{
|
||||||
|
if ( !m_fPhraseStarted )
|
||||||
|
{
|
||||||
|
// Don't queue commands unless a phrase is being processed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUEUEDWM *pWM = new QUEUEDWM;
|
||||||
|
if ( !pWM )
|
||||||
|
{
|
||||||
|
// Out of memory: This WM_COMMAND will get dropped
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pWM->hWnd = hWnd;
|
||||||
|
pWM->message = message;
|
||||||
|
pWM->wParam = wParam;
|
||||||
|
pWM->lParam = lParam;
|
||||||
|
pWM->pNext = NULL;
|
||||||
|
|
||||||
|
if ( m_pTailWM )
|
||||||
|
{
|
||||||
|
// Non-empty queue
|
||||||
|
m_pTailWM->pNext = pWM;
|
||||||
|
m_pTailWM = pWM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Empty queue
|
||||||
|
m_pHeadWM = m_pTailWM = pWM;
|
||||||
|
}
|
||||||
|
} /* CRecoEventMgr::QueueCommand */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::Hypothesis *
|
||||||
|
*---------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called whenever a hypothesis comes back to Dictpad.
|
||||||
|
* Looks for the latest listening point whose timestamp predates ftRecoTime
|
||||||
|
* or for the phrase-start-generated listening point,
|
||||||
|
* whichever came later.
|
||||||
|
* Hands back the range to be replaced by the recognized text, or NULL
|
||||||
|
* if this hypothesis is to be dropped (i.e. did not come between
|
||||||
|
* a PHRASE_START and a RECOGNITION/FALSE_RECOGNITION
|
||||||
|
* Return:
|
||||||
|
* A pointer to an ITextRange in which the hypothesis should go.
|
||||||
|
* NULL in case of error.
|
||||||
|
*****************************************************************************/
|
||||||
|
ITextRange * CRecoEventMgr::Hypothesis( FILETIME ftRecoTime )
|
||||||
|
{
|
||||||
|
if ( !m_fPhraseStarted || !m_pHeadLP )
|
||||||
|
{
|
||||||
|
// This hypothesis did not come between a PHRASE_START and a RECOGNITION,
|
||||||
|
// so we drop it
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the listen points are ordered by most recent first, we are
|
||||||
|
// looking for the first element whose timestamp predates ftRecoTime
|
||||||
|
LISTENPOINT *p = m_pHeadLP;
|
||||||
|
for ( p = m_pHeadLP;
|
||||||
|
p && (CompareFiletimes( ftRecoTime, p->ftTime ) < 0) &&
|
||||||
|
!(p->fFromPhraseStart);
|
||||||
|
p = p->pNext )
|
||||||
|
;
|
||||||
|
|
||||||
|
if ( !p )
|
||||||
|
{
|
||||||
|
// Should not happen! There should at least be a listen point queued
|
||||||
|
// from PhraseStart() on this phrase
|
||||||
|
_ASSERTE( false );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This listen point has now been marked to receive hypothesis text
|
||||||
|
p->fHasHypothesisText = true;
|
||||||
|
|
||||||
|
return p->cpRangeToReplace;
|
||||||
|
} /* CRecoEventMgr::Hypothesis */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::Recognition *
|
||||||
|
*----------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called whenever a recognition comes back to Dictpad.
|
||||||
|
* Looks for the latest listening point whose timestamp predates
|
||||||
|
* ftRecoTime or for the phrase-start-generated listening point,
|
||||||
|
* whichever came later.
|
||||||
|
* Deletes all earlier listening points.
|
||||||
|
* Hands back a duplicate of the range to be replaced by the recognized
|
||||||
|
* text.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* S_FALSE if the recognition was from some phrase that was started
|
||||||
|
* when our grammars were inactive.
|
||||||
|
* Return value from ITextRange::GetDuplicate()
|
||||||
|
*****************************************************************************/
|
||||||
|
HRESULT CRecoEventMgr::Recognition( FILETIME ftRecoTime, ITextRange **ppRecoRange )
|
||||||
|
{
|
||||||
|
|
||||||
|
// A SPEI_RECOGNITION without a SPEI_PHRASE_START means that the phrase was
|
||||||
|
// started when our grammars were inactive, so we'd like to ignore this one.
|
||||||
|
if ( !m_fPhraseStarted || !m_pHeadLP )
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the listen points are ordered by most recent first, we are
|
||||||
|
// looking for the first element whose timestamp predates ftRecoTime
|
||||||
|
LISTENPOINT *p = m_pHeadLP;
|
||||||
|
for ( p = m_pHeadLP;
|
||||||
|
p && (CompareFiletimes( ftRecoTime, p->ftTime ) < 0) && !(p->fFromPhraseStart);
|
||||||
|
p = p->pNext )
|
||||||
|
;
|
||||||
|
|
||||||
|
_ASSERTE( p );
|
||||||
|
if ( !p )
|
||||||
|
{
|
||||||
|
// Should not happen!
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get rid of all subsequent (earlier) listening points
|
||||||
|
DeleteAfter( p );
|
||||||
|
|
||||||
|
// Get the range to return.
|
||||||
|
// Make a duplicate, since this range will be destroyed before the caller
|
||||||
|
// can AddRef it.
|
||||||
|
HRESULT hr = p->cpRangeToReplace->GetDuplicate( ppRecoRange );
|
||||||
|
|
||||||
|
// This listen point will now contain real (non-hypothesis) text
|
||||||
|
p->fHasHypothesisText = false;
|
||||||
|
|
||||||
|
// p will get cleaned up later when DoneProcessingPhrase() is called
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
} /* CRecoEventMgr::Recognition */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::FalseRecognition *
|
||||||
|
*---------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called whenever a false recognition comes back to Dictpad.
|
||||||
|
* Finds the phrase-start-marked listen point
|
||||||
|
* and deletes everything after it
|
||||||
|
*****************************************************************************/
|
||||||
|
void CRecoEventMgr::FalseRecognition()
|
||||||
|
{
|
||||||
|
if ( !m_fPhraseStarted || !m_pHeadLP )
|
||||||
|
{
|
||||||
|
// This means that this is a RECO_OTHER_CONTEXT, or a recognition for
|
||||||
|
// a grammar other than dictation within our own context, neither of
|
||||||
|
// which we care about
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up anything that happened before the start of this utterance
|
||||||
|
for ( LISTENPOINT *p = m_pHeadLP; p && !(p->fFromPhraseStart); p = p->pNext )
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
if ( p )
|
||||||
|
{
|
||||||
|
DeleteAfter( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
// p will get cleaned up later when DoneProcessingPhrase() is called
|
||||||
|
|
||||||
|
} /* CRecoEventMgr::FalseRecognition */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::DoneProcessingPhrase *
|
||||||
|
*-------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Sets m_fPhraseStarted to false.
|
||||||
|
* Calls CleanUp() to clean up the listen point list
|
||||||
|
* and WM_COMMAND queue.
|
||||||
|
*****************************************************************************/
|
||||||
|
void CRecoEventMgr::DoneProcessingPhrase()
|
||||||
|
{
|
||||||
|
m_fPhraseStarted = false;
|
||||||
|
CleanUp();
|
||||||
|
} /* CRecoEventMgr::DoneProcessingPhrase */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::CleanUp *
|
||||||
|
*------------------------*
|
||||||
|
* Description:
|
||||||
|
* Deletes all nodes.
|
||||||
|
* Resends the queued messages and cleans up the queue
|
||||||
|
*****************************************************************************/
|
||||||
|
void CRecoEventMgr::CleanUp()
|
||||||
|
{
|
||||||
|
m_fPhraseStarted = false;
|
||||||
|
|
||||||
|
// Remove any hypothesis text
|
||||||
|
for ( LISTENPOINT *p = m_pHeadLP; p; p = p->pNext )
|
||||||
|
{
|
||||||
|
if ( p->fHasHypothesisText && p->cpRangeToReplace )
|
||||||
|
{
|
||||||
|
p->cpRangeToReplace->SetText( L"" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up the listen point list
|
||||||
|
if ( m_pHeadLP )
|
||||||
|
{
|
||||||
|
DeleteAfter( m_pHeadLP );
|
||||||
|
delete m_pHeadLP;
|
||||||
|
m_pHeadLP = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resend the WM_x messages that had been waiting during the computation
|
||||||
|
// on the phrase and clean up the queue
|
||||||
|
QUEUEDWM *pWM;
|
||||||
|
while ( m_pHeadWM )
|
||||||
|
{
|
||||||
|
pWM = m_pHeadWM;
|
||||||
|
::SendMessage( pWM->hWnd, pWM->message, pWM->wParam, pWM->lParam );
|
||||||
|
|
||||||
|
m_pHeadWM = m_pHeadWM->pNext;
|
||||||
|
delete pWM;
|
||||||
|
}
|
||||||
|
m_pHeadWM = m_pTailWM = NULL;
|
||||||
|
} /* CRecoEventMgr::CleanUp */
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CRecoEventMgr::DeleteAfter *
|
||||||
|
*----------------------------*
|
||||||
|
* Description:
|
||||||
|
* Deletes all nodes after pCutoff.
|
||||||
|
*****************************************************************************/
|
||||||
|
void CRecoEventMgr::DeleteAfter( LISTENPOINT *pCutoff )
|
||||||
|
{
|
||||||
|
if ( pCutoff )
|
||||||
|
{
|
||||||
|
LISTENPOINT *p, *pNextInLine;
|
||||||
|
for ( p = pCutoff->pNext; p; p = pNextInLine )
|
||||||
|
{
|
||||||
|
pNextInLine = p->pNext;
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCutoff->pNext = NULL;
|
||||||
|
} /* CRecoEventMgr::DeleteAfter */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CompareFiletimes *
|
||||||
|
*------------------*
|
||||||
|
* Return:
|
||||||
|
* -1 if ft1 is earlier than ft2
|
||||||
|
* 0 if ft1 == ft2
|
||||||
|
* 1 if ft1 is greater than ft2
|
||||||
|
*****************************************************************************/
|
||||||
|
int CompareFiletimes( FILETIME ft1, FILETIME ft2 )
|
||||||
|
{
|
||||||
|
if ( ft1.dwHighDateTime < ft2.dwHighDateTime )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if ( ft1.dwHighDateTime > ft2.dwHighDateTime )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( ft1.dwLowDateTime < ft2.dwLowDateTime )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if ( ft1.dwLowDateTime > ft2.dwLowDateTime )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* CompareFiletimes */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* AreDisjointRanges *
|
||||||
|
*-------------------*
|
||||||
|
* Description:
|
||||||
|
* Suppose Range1 has limits cpMin1, cpMax1.
|
||||||
|
* Suppose Range2 has limits cpMin2, cpMax2.
|
||||||
|
* Range1 and Range2 are disjoint iff
|
||||||
|
* cpMin2 > cpMax1 OR cpMax2 < cpMin1.
|
||||||
|
* That is, they are disjoint iff there is no overlap and they do not
|
||||||
|
* dovetail.
|
||||||
|
* Return:
|
||||||
|
* true iff the two ranges neither overlap nor abut.
|
||||||
|
*****************************************************************************/
|
||||||
|
bool AreDisjointRanges( ITextRange *pRange1, ITextRange *pRange2 )
|
||||||
|
{
|
||||||
|
if ( !( pRange1 && pRange2 ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
long cpMin1, cpMax1, cpMin2, cpMax2;
|
||||||
|
pRange1->GetStart( &cpMin1 );
|
||||||
|
pRange1->GetEnd( &cpMax1 );
|
||||||
|
pRange2->GetStart( &cpMin2 );
|
||||||
|
pRange2->GetEnd( &cpMax2 );
|
||||||
|
|
||||||
|
return (( cpMin2 > cpMax1 ) || ( cpMax2 < cpMin1 ));
|
||||||
|
} /* AreDisjointRanges */
|
101
mp/src/utils/sapi51/Samples/CPP/DictPad/recomgr.h
Normal file
101
mp/src/utils/sapi51/Samples/CPP/DictPad/recomgr.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* recomgr.h
|
||||||
|
* Support for queuing insertion points and correctly placing
|
||||||
|
* recognized text
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __RECOMGR_H
|
||||||
|
#define __RECOMGR_H
|
||||||
|
|
||||||
|
// A structure that represents a range waiting for a possible dictation result
|
||||||
|
typedef struct LISTENPOINT
|
||||||
|
{
|
||||||
|
CComPtr<ITextRange> cpRangeToReplace; // The entire range to be replaced
|
||||||
|
// when a recognition comes back
|
||||||
|
FILETIME ftTime;
|
||||||
|
bool fFromPhraseStart; // Indicates that this
|
||||||
|
// listening point was added
|
||||||
|
// because a phrasestart
|
||||||
|
// happened
|
||||||
|
bool fHasHypothesisText; // Indicates that this listen point
|
||||||
|
// has some hypothesis text associated
|
||||||
|
// with it
|
||||||
|
LISTENPOINT *pNext;
|
||||||
|
} LISTENPOINT;
|
||||||
|
|
||||||
|
// A queued message
|
||||||
|
typedef struct QUEUEDWM
|
||||||
|
{
|
||||||
|
HWND hWnd;
|
||||||
|
UINT message;
|
||||||
|
WPARAM wParam;
|
||||||
|
LPARAM lParam;
|
||||||
|
QUEUEDWM *pNext;
|
||||||
|
} QUEUEDWM;
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* CRecoEventMgr *
|
||||||
|
*---------------*
|
||||||
|
* Handles the placement of recognized text according to the timing of
|
||||||
|
* the events
|
||||||
|
******************************************************************************/
|
||||||
|
class CRecoEventMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CRecoEventMgr( HINSTANCE hInstance );
|
||||||
|
~CRecoEventMgr();
|
||||||
|
|
||||||
|
void SetTextSel( ITextSelection *pTextSel ) { m_pTextSel = pTextSel; }
|
||||||
|
bool IsProcessingPhrase() { return m_fPhraseStarted; }
|
||||||
|
|
||||||
|
// Methods called by app to notify CRecoEventMgr of events
|
||||||
|
HRESULT PhraseStart( ITextRange &rSelRange );
|
||||||
|
// Called when a PHRASE_START
|
||||||
|
// notification is received
|
||||||
|
HRESULT SelNotify( ITextRange &rSelRange ); // Called whenever the
|
||||||
|
// selection has changed
|
||||||
|
bool IsEditable( ITextRange *pRange, ITextRange **ppNextEditableRange );
|
||||||
|
// Returns false iff there is
|
||||||
|
// currently a reco computation
|
||||||
|
// going on and the current sel
|
||||||
|
// overlaps a listen point
|
||||||
|
void QueueCommand( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
|
||||||
|
// Called when a WM_ messsage
|
||||||
|
// is received during a
|
||||||
|
// reco computation
|
||||||
|
ITextRange * Hypothesis( FILETIME ftRecoTime );
|
||||||
|
HRESULT Recognition( FILETIME ftRecoTime, ITextRange **ppRecoRange );
|
||||||
|
void FalseRecognition();
|
||||||
|
|
||||||
|
// Methods called by app when phrase-computation is over
|
||||||
|
void DoneProcessingPhrase(); // Turns off m_fPhraseStarted
|
||||||
|
// and cleans up the list
|
||||||
|
private:
|
||||||
|
void CleanUp(); // Frees up the lists and
|
||||||
|
// unleashes the waiting WM_s
|
||||||
|
|
||||||
|
void DeleteAfter( LISTENPOINT *pCutoff );
|
||||||
|
// Will delete all points in
|
||||||
|
// in the listening point list
|
||||||
|
// after pCutoff
|
||||||
|
// the head of the list
|
||||||
|
|
||||||
|
HINSTANCE m_hInst; // HINSTANCE for LoadString()
|
||||||
|
bool m_fPhraseStarted; // true iff there is a phrase being processed
|
||||||
|
ITextSelection *m_pTextSel; // The selection in dictpad's window
|
||||||
|
LISTENPOINT *m_pHeadLP; // List of listening points, most recent first
|
||||||
|
QUEUEDWM *m_pHeadWM; // Queue of WM_s
|
||||||
|
QUEUEDWM *m_pTailWM;
|
||||||
|
|
||||||
|
}; /* class CRecoEventMgr */
|
||||||
|
|
||||||
|
// Helper function
|
||||||
|
int CompareFiletimes( FILETIME ft1, FILETIME ft2 );
|
||||||
|
bool AreDisjointRanges( ITextRange *pRange1, ITextRange *pRange2 );
|
||||||
|
bool AreNonOverlappingRanges( ITextRange *pRange1, ITextRange *pRange2 );
|
||||||
|
|
||||||
|
#endif // __RECOMGR_H
|
136
mp/src/utils/sapi51/Samples/CPP/DictPad/resource.h
Normal file
136
mp/src/utils/sapi51/Samples/CPP/DictPad/resource.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Developer Studio generated include file.
|
||||||
|
// Used by dictpad.rc
|
||||||
|
//
|
||||||
|
#define IDC_MYICON 2
|
||||||
|
#define IDC_REMOVEFROMLEX 3
|
||||||
|
#define IDC_ADDBACKTOLEX 4
|
||||||
|
#define IDD_DICTPAD_DIALOG 101
|
||||||
|
#define IDD_ABOUTBOX 102
|
||||||
|
#define IDS_APP_TITLE 103
|
||||||
|
#define IDM_ABOUT 104
|
||||||
|
#define IDM_EXIT 105
|
||||||
|
#define IDS_HELLO 106
|
||||||
|
#define IDI_DICTPAD 107
|
||||||
|
#define IDI_SMALL 108
|
||||||
|
#define IDC_DICTPAD 109
|
||||||
|
#define IDC_TOOLBAR 110
|
||||||
|
#define IDM_PLAY 111
|
||||||
|
#define IDM_MIC_TOGGLE 112
|
||||||
|
#define IDC_STATUSBAR 113
|
||||||
|
#define IDR_MAINFRAME 128
|
||||||
|
#define IDB_BITMAP2 132
|
||||||
|
#define IDB_BITMAP1 134
|
||||||
|
#define IDR_TOOLBAR 135
|
||||||
|
#define IDB_BITMAP3 139
|
||||||
|
#define IDR_DICTATION_MODE_CFG 140
|
||||||
|
#define IDR_COMMAND_MODE_CFG 141
|
||||||
|
#define IDD_ADDREMOVEWORDS 142
|
||||||
|
#define IDD_ADDREMOVEBOX 142
|
||||||
|
#define IDD_WORDPRONUNCIATIONBOX 142
|
||||||
|
#define IDD_ADDREMOVEWORDSBOX 146
|
||||||
|
#define IDD_REVIEWPRONUNCIATIONSBOX 147
|
||||||
|
#define IDD_USERLEXBOX 148
|
||||||
|
#define IDR_TOOLBAR1 149
|
||||||
|
#define IDD_ALTERNATES 154
|
||||||
|
#define IDC_ABOUT_DICTPAD_VERSION 1000
|
||||||
|
#define IDC_ABOUT_COMPONENTS 1001
|
||||||
|
#define IDC_CHANGE 1006
|
||||||
|
#define IDC_DELETE 1007
|
||||||
|
#define IDC_PLAY 1009
|
||||||
|
#define IDC_SOUNDSLIKE 1011
|
||||||
|
#define IDC_WORD 1013
|
||||||
|
#define IDC_COMBO_AUDIO 1014
|
||||||
|
#define IDC_COMBO_POS 1018
|
||||||
|
#define IDC_LIST_PRONS 1025
|
||||||
|
#define IDC_ADD 1027
|
||||||
|
#define IDC_RADIO_SINGLEWORD 1030
|
||||||
|
#define IDC_RADIO_ADDFROMDOC 1031
|
||||||
|
#define IDC_LIST_NEWWORDS 1031
|
||||||
|
#define IDC_RADIO_ADDFROMSEL 1032
|
||||||
|
#define IDC_RADIO_ADDFROMSPELLING 1033
|
||||||
|
#define IDC_REMOVE 1034
|
||||||
|
#define IDC_LIST_WORDSINLEX 1034
|
||||||
|
#define IDC_LIST_WORDSOUTOFLEX 1035
|
||||||
|
#define IDC_LIST1 1037
|
||||||
|
#define IDC_CANDIDATELIST 1037
|
||||||
|
#define IDM_FONT 32771
|
||||||
|
#define IDM_DICTATION_MODE 32772
|
||||||
|
#define IDS_TB0 32773
|
||||||
|
#define IDM_COMMAND_MODE 32774
|
||||||
|
#define ID_VOICE_ADDREMOVEWORDS 32775
|
||||||
|
#define IDM_VOICE_ADDREMOVEWORDS 32776
|
||||||
|
#define IDM_ADDREMOVEWORDS 32776
|
||||||
|
#define IDM_COMMANDS 32777
|
||||||
|
#define IDS_ADD 32778
|
||||||
|
#define IDM_VOICE_TRAINING 32779
|
||||||
|
#define IDS_CHANGE 32779
|
||||||
|
#define IDM_WHOLE_WORDS 32780
|
||||||
|
#define IDS_NONEWWORDS 32780
|
||||||
|
#define IDM_AUTO_PLAYBACK 32781
|
||||||
|
#define IDS_NOWORDSADDED 32781
|
||||||
|
#define IDS_TB1 32782
|
||||||
|
#define IDS_WAITING 32782
|
||||||
|
#define IDM_MODE_TOGGLE 32783
|
||||||
|
#define IDS_INVALIDFILEFORMAT 32783
|
||||||
|
#define IDS_CANNOTOPEN 32784
|
||||||
|
#define IDS_ERRORSAVING 32785
|
||||||
|
#define IDS_CANNOTSAVE 32786
|
||||||
|
#define IDS_CONFIRMCLOSE 32787
|
||||||
|
#define IDS_MICROPHONESETUPWIZARD 32791
|
||||||
|
#define IDS_ACCESSDENIED 32793
|
||||||
|
#define IDS_CANNOTSWITCHMODES 32794
|
||||||
|
#define IDS_CANNOTFILENEW 32795
|
||||||
|
#define ID_BUTTON32796 32796
|
||||||
|
#define IDS_UPDATEERROR 32796
|
||||||
|
#define ID_BUTTON32797 32797
|
||||||
|
#define IDS_UNSUPPORTEDLANG 32797
|
||||||
|
#define ID_BUTTON32798 32798
|
||||||
|
#define ID_BUTTON32799 32799
|
||||||
|
#define ID_BUTTON32800 32800
|
||||||
|
#define ID_BUTTON32801 32801
|
||||||
|
#define ID_BUTTON32802 32802
|
||||||
|
#define ID_BUTTON32803 32803
|
||||||
|
#define ID_BUTTON32804 32804
|
||||||
|
#define ID_BUTTON32805 32805
|
||||||
|
#define ID_BUTTON32806 32806
|
||||||
|
#define ID_BUTTON32807 32807
|
||||||
|
#define ID_BUTTON32808 32808
|
||||||
|
#define ID_BUTTON32809 32809
|
||||||
|
#define ID_BUTTON32810 32810
|
||||||
|
#define ID_BUTTON32811 32811
|
||||||
|
#define ID_BUTTON32812 32812
|
||||||
|
#define ID_BUTTON32813 32813
|
||||||
|
#define ID_BUTTON32814 32814
|
||||||
|
#define ID_BUTTON32815 32815
|
||||||
|
#define ID_FILE_OPEN 32816
|
||||||
|
#define ID_FILE_SAVE 32817
|
||||||
|
#define ID_FILE_SAVEAS 32818
|
||||||
|
#define ID_FILE_NEW 32819
|
||||||
|
#define ID_EDIT_UNDO 32820
|
||||||
|
#define ID_EDIT_REDO 32821
|
||||||
|
#define ID_EDIT_CUT 32822
|
||||||
|
#define ID_EDIT_COPY 32823
|
||||||
|
#define ID_EDIT_PASTE 32824
|
||||||
|
#define ID_HELP_CONTENTS 32825
|
||||||
|
#define ID_HELP_SEARCH 32826
|
||||||
|
#define ID_HELP_INDEX 32827
|
||||||
|
#define IDM_USERLEX 32828
|
||||||
|
#define IDB_DICTMODE 32829
|
||||||
|
#define IDB_COMMANDMODE 32830
|
||||||
|
#define IDB_PLAY 32831
|
||||||
|
#define IDB_MICTOGGLE 32832
|
||||||
|
#define IDM_MICROPHONE_SETUP 32835
|
||||||
|
#define IDM_SHAREDENGINE 32836
|
||||||
|
#define IDC_LIST_ALTS 32837
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 157
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 32839
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1038
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 114
|
||||||
|
#endif
|
||||||
|
#endif
|
755
mp/src/utils/sapi51/Samples/CPP/DictPad/resultcontainer.cpp
Normal file
755
mp/src/utils/sapi51/Samples/CPP/DictPad/resultcontainer.cpp
Normal file
@ -0,0 +1,755 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* resultcontainer.cpp
|
||||||
|
* This module contains the definition of CResultContainer.
|
||||||
|
* CResultContainer makes all of the recognition-object-
|
||||||
|
* specific SAPI5 calls
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "resultcontainer.h"
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::CResultContainer *
|
||||||
|
*------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Constructor for the CResultContainer class.
|
||||||
|
* A CResultContainer is created by the first CDictationRun
|
||||||
|
* to be created for a given result object.
|
||||||
|
**********************************************************************/
|
||||||
|
CResultContainer::CResultContainer( ISpRecoResult &rResult,
|
||||||
|
CDictationRun &rFirstOwner,
|
||||||
|
CPhraseReplacement &rPhraseReplacement ) :
|
||||||
|
m_cpRecoResult( &rResult ),
|
||||||
|
m_pPhraseReplacement( &rPhraseReplacement ),
|
||||||
|
m_pOwnerListHead( NULL ),
|
||||||
|
m_cLastRequestedAltsReturned( 0 ),
|
||||||
|
m_ulStartOfLastRequestedAlts( 0 ),
|
||||||
|
m_cElementsInLastRequestedAlts( 0 )
|
||||||
|
{
|
||||||
|
// The owner should go onto the list
|
||||||
|
m_pOwnerListHead = new OWNERNODE;
|
||||||
|
if ( m_pOwnerListHead )
|
||||||
|
{
|
||||||
|
m_pOwnerListHead->pOwner = &rFirstOwner;
|
||||||
|
m_pOwnerListHead->pNext = NULL;
|
||||||
|
}
|
||||||
|
// If the allocation failed, all calls that need it
|
||||||
|
// will return E_OUTOFMEMORY
|
||||||
|
|
||||||
|
// Zero out the requested phrase alternates array
|
||||||
|
memset( (void *) m_apLastRequestedPhraseAlts, 0,
|
||||||
|
ALT_REQUEST_COUNT * sizeof( ISpPhraseAlt *) );
|
||||||
|
} /* CResultContainer::CResultContainer */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::~CResultContainer *
|
||||||
|
*-------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Destructor for the CResultContainer class.
|
||||||
|
* This object gets destroyed when there are no longer
|
||||||
|
* any CDictationRuns referencing it.
|
||||||
|
**********************************************************************/
|
||||||
|
CResultContainer::~CResultContainer()
|
||||||
|
{
|
||||||
|
_ASSERTE( !m_pOwnerListHead );
|
||||||
|
|
||||||
|
if ( m_pPhraseReplacement )
|
||||||
|
{
|
||||||
|
delete m_pPhraseReplacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release any ISpPhraseAlt's that are still around from the
|
||||||
|
// last call to ISpPhrase::GetAlternates()
|
||||||
|
for (int i = 0; i < ALT_REQUEST_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (m_apLastRequestedPhraseAlts[i])
|
||||||
|
{
|
||||||
|
m_apLastRequestedPhraseAlts[i]->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* CResultContainer::~CResultContainer */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::AddOwner *
|
||||||
|
*----------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called whenever a new CDictationRun is created to use this
|
||||||
|
* same RecoResult. Adds that CDictationRun to the front of
|
||||||
|
* the list of owners.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_OUTOFMEMORY
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CResultContainer::AddOwner( CDictationRun &rNewOwner )
|
||||||
|
{
|
||||||
|
if ( !m_pOwnerListHead )
|
||||||
|
{
|
||||||
|
_ASSERTE( false );
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
OWNERNODE *pNode = new OWNERNODE;
|
||||||
|
if ( pNode )
|
||||||
|
{
|
||||||
|
pNode->pNext = m_pOwnerListHead;
|
||||||
|
pNode->pOwner = &rNewOwner;
|
||||||
|
m_pOwnerListHead = pNode;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
} /* CResultContainer::AddOwner */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::DeleteOwner *
|
||||||
|
*-------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called whenever a DictationRun using this RecoResult
|
||||||
|
* has been deleted. Removes the CDictationRun from the
|
||||||
|
* list and deletes itself if that was the last owner
|
||||||
|
**********************************************************************/
|
||||||
|
void CResultContainer::DeleteOwner( CDictationRun &rOldOwner )
|
||||||
|
{
|
||||||
|
_ASSERTE( m_pOwnerListHead );
|
||||||
|
if ( !m_pOwnerListHead )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OWNERNODE **ppNode;
|
||||||
|
for ( ppNode = &m_pOwnerListHead;
|
||||||
|
(*ppNode) && ((*ppNode)->pOwner != &rOldOwner);
|
||||||
|
ppNode = &((*ppNode)->pNext) )
|
||||||
|
;
|
||||||
|
|
||||||
|
if ( *ppNode )
|
||||||
|
{
|
||||||
|
// Found: Delete it
|
||||||
|
OWNERNODE *pNodeToDelete = *ppNode;
|
||||||
|
*ppNode = (*ppNode)->pNext;
|
||||||
|
delete pNodeToDelete;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Should be on the list!
|
||||||
|
_ASSERTE( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !m_pOwnerListHead )
|
||||||
|
{
|
||||||
|
// There are no more CDictationRuns referencing this
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
} /* CResultContainer::DeleteOwner */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::SpeakAudio *
|
||||||
|
*------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Calls ISpRecoResult::SpeakAudio() on the recoresult.
|
||||||
|
* Converts the arguments to pre-replacement elements
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* S_FALSE if no elements are to be spoken.
|
||||||
|
* Return value of CPhraseReplacement conversion routines
|
||||||
|
* Return value of ISpRecoResult::SpeakAudio()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CResultContainer::SpeakAudio( ULONG ulStartElement,
|
||||||
|
ULONG cElements )
|
||||||
|
{
|
||||||
|
if (!cElements)
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the start and end to phrase element indices
|
||||||
|
// as seen from the result object's point of view
|
||||||
|
ULONG ulPreReplStart;
|
||||||
|
ULONG ulPreReplEnd;
|
||||||
|
ULONG cPreReplElts;
|
||||||
|
HRESULT hr = m_pPhraseReplacement->PostToPreReplacementIndex(
|
||||||
|
ulStartElement, &ulPreReplStart );
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = m_pPhraseReplacement->PostToPreReplacementIndex(
|
||||||
|
ulStartElement + cElements, &ulPreReplEnd );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call ISpRecoResult::SpeakAudio()
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
cPreReplElts = ulPreReplEnd - ulPreReplStart;
|
||||||
|
hr = m_cpRecoResult->SpeakAudio(
|
||||||
|
ulPreReplStart, cPreReplElts, SPF_ASYNC, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
} /* CResultContainer::SpeakAudio */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::GetAlternatesText *
|
||||||
|
*-------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called to get the text of the alternates for
|
||||||
|
* a specific range of elements in this result.
|
||||||
|
* ppszCoMemText is expected to point to a buffer
|
||||||
|
* of size at least sizeof( WCHAR * ) * ulRequestCount,
|
||||||
|
* and the text in it will be CoTaskMemAlloced.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* S_FALSE if there are no alternates
|
||||||
|
* E_POINTER
|
||||||
|
* return value of CResultContainer::GetAlternates()
|
||||||
|
* return value of CResultContainer::GetAltText()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CResultContainer::GetAlternatesText( ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulRequestCount,
|
||||||
|
WCHAR **ppszCoMemText,
|
||||||
|
ULONG *pcPhrasesReturned )
|
||||||
|
{
|
||||||
|
SPDBG_FUNC("CResultContainer::GetAlternatesText");
|
||||||
|
if ( !ppszCoMemText || !pcPhrasesReturned )
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get as many alternates as we can
|
||||||
|
ULONG cAvailableAlts;
|
||||||
|
HRESULT hr = GetAlternates( ulStartElement, cElements, ulRequestCount,
|
||||||
|
&cAvailableAlts );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check: We didn't get more than we asked for
|
||||||
|
_ASSERTE( cAvailableAlts <= ulRequestCount );
|
||||||
|
|
||||||
|
if ( !cAvailableAlts )
|
||||||
|
{
|
||||||
|
// No alternates
|
||||||
|
*pcPhrasesReturned = 0;
|
||||||
|
*ppszCoMemText = NULL;
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null out the pointers to text buffers first
|
||||||
|
memset(ppszCoMemText, 0, ulRequestCount * sizeof(WCHAR *));
|
||||||
|
|
||||||
|
// Get the text
|
||||||
|
for ( ULONG ulAlt = 0;
|
||||||
|
SUCCEEDED(hr) && (ulAlt < cAvailableAlts);
|
||||||
|
ulAlt++ )
|
||||||
|
{
|
||||||
|
// ppszCoMemText[ulAlt] is the ulAlt'th (WCHAR *)
|
||||||
|
// in the array.
|
||||||
|
// Its address will give us a WCHAR ** which will
|
||||||
|
// point to a buffer that is to be CoTaskMemAlloced
|
||||||
|
// by GetAltText()
|
||||||
|
hr = GetAltText( ulStartElement, cElements, ulAlt,
|
||||||
|
&(ppszCoMemText[ulAlt]), NULL );
|
||||||
|
}
|
||||||
|
*pcPhrasesReturned = cAvailableAlts;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
} /* CResultContainer::GetAlternatesText */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::GetAlternates *
|
||||||
|
*---------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Gets the ISpPhraseAlts for this range of elements
|
||||||
|
* (indices are given taking replacement into account).
|
||||||
|
* The phrase alternates are pointed to by
|
||||||
|
* m_apLastRequestedPhraseAlts.
|
||||||
|
* It is very likely that GetAlternates() would be called
|
||||||
|
* numerous times consecutively for the same set of
|
||||||
|
* alternates. Thus, these are cached between calls.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_INVALIDARG: Out-of-bounds elements
|
||||||
|
* Return value of CPhraseReplacement conversion routines
|
||||||
|
* Return value of ISpRecoResult::GetAlternates
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CResultContainer::GetAlternates( ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulRequestCount,
|
||||||
|
ULONG *pcPhrasesReturned )
|
||||||
|
{
|
||||||
|
// First check to see if we have these alternates cached.
|
||||||
|
// We check that there is at least one alternate cached,
|
||||||
|
// that the alternates are for the same set of phrase elements,
|
||||||
|
// and that there are enough.
|
||||||
|
if ( m_apLastRequestedPhraseAlts[0] &&
|
||||||
|
( m_ulStartOfLastRequestedAlts == ulStartElement ) &&
|
||||||
|
( m_cElementsInLastRequestedAlts == cElements ) &&
|
||||||
|
( m_cLastRequestedAltsReturned >= ulRequestCount) )
|
||||||
|
{
|
||||||
|
if ( pcPhrasesReturned )
|
||||||
|
{
|
||||||
|
// We already have these alternates, so don't bother
|
||||||
|
// getting them again
|
||||||
|
*pcPhrasesReturned = __min(
|
||||||
|
ulRequestCount, m_cLastRequestedAltsReturned );
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (ulStartElement + cElements) >
|
||||||
|
m_pPhraseReplacement->GetNumReplacementElements() )
|
||||||
|
{
|
||||||
|
// Out of bounds
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the start and end to phrase element indices
|
||||||
|
// as seen from the result object's point of view
|
||||||
|
ULONG ulPreReplStart;
|
||||||
|
ULONG ulPreReplLast;
|
||||||
|
HRESULT hr = m_pPhraseReplacement->PostToPreReplacementIndex(
|
||||||
|
ulStartElement, &ulPreReplStart );
|
||||||
|
if ( SUCCEEDED(hr) )
|
||||||
|
{
|
||||||
|
hr = m_pPhraseReplacement->PostToPreReplacementIndex(
|
||||||
|
ulStartElement + cElements, &ulPreReplLast );
|
||||||
|
}
|
||||||
|
ULONG cPreReplElements = ulPreReplLast - ulPreReplStart;
|
||||||
|
|
||||||
|
// Release any ISpPhraseAlts that are around from last time
|
||||||
|
for (int i = 0; i < ALT_REQUEST_COUNT; i++)
|
||||||
|
{
|
||||||
|
if ( m_apLastRequestedPhraseAlts[i] )
|
||||||
|
{
|
||||||
|
m_apLastRequestedPhraseAlts[i]->Release();
|
||||||
|
m_apLastRequestedPhraseAlts[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get as many alternates as we can by calling
|
||||||
|
// ISpRecoResult::GetAlternates()
|
||||||
|
ULONG cPhrasesReturned;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = m_cpRecoResult->GetAlternates( ulPreReplStart,
|
||||||
|
cPreReplElements, ulRequestCount, m_apLastRequestedPhraseAlts,
|
||||||
|
&cPhrasesReturned );
|
||||||
|
}
|
||||||
|
if ( pcPhrasesReturned )
|
||||||
|
{
|
||||||
|
*pcPhrasesReturned = cPhrasesReturned;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache information about this alternate request
|
||||||
|
m_ulStartOfLastRequestedAlts = ulStartElement;
|
||||||
|
m_cElementsInLastRequestedAlts = cElements;
|
||||||
|
m_cLastRequestedAltsReturned = cPhrasesReturned;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
} /* CResultContainer::GetAlternates */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::GetAltInfo *
|
||||||
|
*------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Given the alternates index, gets the info for the
|
||||||
|
* alternate (i.e. which elements it replaces in the
|
||||||
|
* parent and how many elements it has).
|
||||||
|
* Returns element indices TAKING REPLACEMENTS INTO
|
||||||
|
* ACCOUNT, unless the fReturnPostReplIndices flag has
|
||||||
|
* been set to false (it is set to true by default).
|
||||||
|
*
|
||||||
|
* If the end of the alternate falls in the middle of
|
||||||
|
* a replacement, then the result indices are expanded
|
||||||
|
* to include the entire replacement.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_FAIL if we couldn't get ulAlternateIndex alternates
|
||||||
|
* Return value of CResultContainer::GetAlternates()
|
||||||
|
* Return value of ISpPhraseAlt::GetAltInfo()
|
||||||
|
* Return value of
|
||||||
|
* CResultContainer::ExpandToIncludeWholeReplacements()
|
||||||
|
* Return value of CPhraseReplacement::Initialize()
|
||||||
|
* Return value of CPhraseReplacement conversion routines
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CResultContainer::GetAltInfo( ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulAlternateIndex,
|
||||||
|
ULONG *pulStartInParent,
|
||||||
|
ULONG *pcEltsInParent,
|
||||||
|
ULONG *pcEltsInAlt,
|
||||||
|
bool fReturnPostReplIndices)
|
||||||
|
{
|
||||||
|
// First make sure we actually have this alternate
|
||||||
|
ULONG cPhrasesReturned;
|
||||||
|
HRESULT hr = GetAlternates(
|
||||||
|
ulStartElement, cElements, ulAlternateIndex + 1, &cPhrasesReturned );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
if ( cPhrasesReturned < (ulAlternateIndex + 1) )
|
||||||
|
{
|
||||||
|
// There aren't enough alternates to accommodate
|
||||||
|
// this one
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check: The pointer to the ISpPhraseAlt for this
|
||||||
|
// alternate is non-NULL
|
||||||
|
_ASSERTE( m_apLastRequestedPhraseAlts[ ulAlternateIndex ] );
|
||||||
|
|
||||||
|
// Call to ISpPhraseAlt::GetAltInfo()
|
||||||
|
ULONG ulStartInParent;
|
||||||
|
ULONG cEltsInParent;
|
||||||
|
ULONG cEltsInAlt;
|
||||||
|
hr = (m_apLastRequestedPhraseAlts[ ulAlternateIndex ])->GetAltInfo(
|
||||||
|
NULL, &ulStartInParent, &cEltsInParent, &cEltsInAlt );
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
// Debug code for seeing the text of the entire alternate
|
||||||
|
// (which covers the entire parent phrase) and for seeing
|
||||||
|
// the text for just the part of the alternate that
|
||||||
|
// covers the elements in the parent that we are interested in
|
||||||
|
WCHAR * pwszWhole = 0;
|
||||||
|
WCHAR * pwszAlt = 0;
|
||||||
|
BYTE b;
|
||||||
|
m_apLastRequestedPhraseAlts[ ulAlternateIndex ]->GetText(
|
||||||
|
SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, true, &pwszWhole, &b );
|
||||||
|
m_apLastRequestedPhraseAlts[ ulAlternateIndex ]->GetText(
|
||||||
|
ulStartInParent, cEltsInAlt, true, &pwszAlt, &b );
|
||||||
|
::CoTaskMemFree( pwszWhole );
|
||||||
|
::CoTaskMemFree( pwszAlt );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If there is replaced (ITNed) text anywhere in this set of
|
||||||
|
// elements in the parent, we should be getting alternate
|
||||||
|
// text for the entire replacement.
|
||||||
|
// That is, if a replacement covers the word "thirty" in the
|
||||||
|
// phrase "I have thirty nine dollars", we should also be
|
||||||
|
// showing alternate text for the elements "nine dollars",
|
||||||
|
// since it appears to all be one element ("$39.00") to the
|
||||||
|
// user
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
const ULONG cEltsInParentBeforeExpansion = cEltsInParent;
|
||||||
|
|
||||||
|
// Expand the endpoints to include entire replacements
|
||||||
|
hr = m_pPhraseReplacement->ExpandToIncludeWholeReplacements(
|
||||||
|
&ulStartInParent, &cEltsInParent );
|
||||||
|
_ASSERTE( SUCCEEDED( hr ) );
|
||||||
|
|
||||||
|
// Adjust the number of elements in the alternate accordingly
|
||||||
|
// (all of the extra elements we have just included are the
|
||||||
|
// same in the alternate as they are in the parent, so it
|
||||||
|
// will be the same number of extra elements in the alternate
|
||||||
|
cEltsInAlt += cEltsInParent - cEltsInParentBeforeExpansion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !fReturnPostReplIndices )
|
||||||
|
{
|
||||||
|
// We're done; no need to convert, since the caller wants
|
||||||
|
// output in phrase element indices from the result object's
|
||||||
|
// point of view
|
||||||
|
if ( pulStartInParent )
|
||||||
|
{
|
||||||
|
*pulStartInParent = ulStartInParent;
|
||||||
|
}
|
||||||
|
if ( pcEltsInParent )
|
||||||
|
{
|
||||||
|
*pcEltsInParent = cEltsInParent;
|
||||||
|
}
|
||||||
|
if ( pcEltsInAlt )
|
||||||
|
{
|
||||||
|
*pcEltsInAlt = cEltsInAlt;
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert these element indices to post-replacement indices
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
// First convert the start element
|
||||||
|
ULONG ulPostReplStartInParent;
|
||||||
|
hr = m_pPhraseReplacement->PreToPostReplacementIndex(
|
||||||
|
ulStartInParent, &ulPostReplStartInParent );
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
if ( pulStartInParent )
|
||||||
|
{
|
||||||
|
*pulStartInParent = ulPostReplStartInParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the end element to determine how many post-replacement
|
||||||
|
// elements this alternate replaces
|
||||||
|
if ( pcEltsInParent )
|
||||||
|
{
|
||||||
|
ULONG ulEndInParent = ulStartInParent + cEltsInParent;
|
||||||
|
ULONG ulEndPostReplElement;
|
||||||
|
hr = m_pPhraseReplacement->PreToPostReplacementIndex(
|
||||||
|
ulEndInParent, &ulEndPostReplElement );
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
*pcEltsInParent = ulEndPostReplElement - ulPostReplStartInParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the number of elements in the alternate, if that was requested
|
||||||
|
if ( SUCCEEDED(hr) && pcEltsInAlt )
|
||||||
|
{
|
||||||
|
// Since this ISpPhraseAlt is a completely different ISpPhrase
|
||||||
|
// from the one associated with m_cpRecoResult, we have to
|
||||||
|
// construct a new CPhraseReplacement object to deal specifically
|
||||||
|
// with this phrase.
|
||||||
|
CPhraseReplacement newPhraseRepl;
|
||||||
|
hr = newPhraseRepl.Initialize(*(m_apLastRequestedPhraseAlts[ ulAlternateIndex ]));
|
||||||
|
|
||||||
|
// First convert the start element
|
||||||
|
ULONG ulPostReplStartInAlt;
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
hr = newPhraseRepl.PreToPostReplacementIndex(
|
||||||
|
ulStartInParent, &ulPostReplStartInAlt );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the end element to determine how many post-replacement
|
||||||
|
// elements this alternate replaces
|
||||||
|
ULONG ulEndInAlt = ulStartInParent + cEltsInAlt;
|
||||||
|
ULONG ulEndPostReplElement;
|
||||||
|
if ( SUCCEEDED(hr) )
|
||||||
|
{
|
||||||
|
hr = newPhraseRepl.PreToPostReplacementIndex(
|
||||||
|
ulEndInAlt, &ulEndPostReplElement );
|
||||||
|
}
|
||||||
|
*pcEltsInAlt = ulEndPostReplElement - ulPostReplStartInAlt;
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
} /* CResultContainer::GetAltInfo */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::GetAltText *
|
||||||
|
*------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Given the alternates index, gets the text for the
|
||||||
|
* alternate and display attributes.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* Return value of CResultContainer::GetAlternates()
|
||||||
|
* Return value of CResultContainer::GetAltInfo()
|
||||||
|
* Return value of ISpPhraseAlt::GetText()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CResultContainer::GetAltText( ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulAlternateIndex,
|
||||||
|
WCHAR **ppszCoMemText,
|
||||||
|
BYTE *pbDisplayAttributes )
|
||||||
|
{
|
||||||
|
// First make sure we actually have this alternate
|
||||||
|
ULONG cPhrasesReturned;
|
||||||
|
HRESULT hr = GetAlternates(
|
||||||
|
ulStartElement, cElements, ulAlternateIndex + 1, &cPhrasesReturned );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
if ( cPhrasesReturned < (ulAlternateIndex + 1) )
|
||||||
|
{
|
||||||
|
// There aren't enough alternates to accommodate
|
||||||
|
// this one
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check: The pointer to the ISpPhraseAlt for this
|
||||||
|
// alternate is non-NULL
|
||||||
|
_ASSERTE( m_apLastRequestedPhraseAlts[ ulAlternateIndex ] );
|
||||||
|
|
||||||
|
// Find out what elements in the parent this alternate replaces
|
||||||
|
// Note that we do NOT want text replacements taken into effect,
|
||||||
|
// since we are calling ISpPhrase::GetText() directly with
|
||||||
|
// these phrase element indices, so we need those indices
|
||||||
|
// from the result object's point of view
|
||||||
|
ULONG ulStartInParent;
|
||||||
|
ULONG cEltsInParent;
|
||||||
|
ULONG cEltsInAlt;
|
||||||
|
hr = GetAltInfo( ulStartElement, cElements, ulAlternateIndex,
|
||||||
|
&ulStartInParent, &cEltsInParent, &cEltsInAlt, false );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call to ISpPhraseAlt::GetText()
|
||||||
|
return m_apLastRequestedPhraseAlts[ ulAlternateIndex ]->GetText(
|
||||||
|
ulStartInParent, cEltsInAlt, true, ppszCoMemText, pbDisplayAttributes );
|
||||||
|
} /* CResultContainer::GetAltText */
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::ChooseAlternate *
|
||||||
|
*-----------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called when the caller wishes to commit one of the alternates.
|
||||||
|
* If pbDisplayAttributes is non-NULL, hands back the display
|
||||||
|
* attributes of the alternate text going in.
|
||||||
|
* Adjusts the phrase element mapping in CPhraseReplacement
|
||||||
|
* to the new result object.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* Return value of CResultContainer::GetAlternates()
|
||||||
|
* Return value of CResultContainer::GetAltText()
|
||||||
|
* Return value of CResultContainer::NotifyOwnersOfCommit()
|
||||||
|
* Return value of ISpPhraseAlt::Commit()
|
||||||
|
* Return value of CPhraseReplacement::Initialize()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CResultContainer::ChooseAlternate( ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulAlternateIndex,
|
||||||
|
BYTE *pbDisplayAttributes )
|
||||||
|
{
|
||||||
|
// First make sure we actually have this alternate
|
||||||
|
ULONG cPhrasesReturned;
|
||||||
|
HRESULT hr = GetAlternates(
|
||||||
|
ulStartElement, cElements, ulAlternateIndex + 1, &cPhrasesReturned );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
if ( cPhrasesReturned < (ulAlternateIndex + 1) )
|
||||||
|
{
|
||||||
|
// There aren't enough alternates to accommodate
|
||||||
|
// this one
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check: The pointer to the ISpPhraseAlt for this
|
||||||
|
// alternate is non-NULL
|
||||||
|
_ASSERTE( m_apLastRequestedPhraseAlts[ ulAlternateIndex ] );
|
||||||
|
|
||||||
|
// If there is interest in the display attributes for the alternate,
|
||||||
|
// get them
|
||||||
|
if ( pbDisplayAttributes )
|
||||||
|
{
|
||||||
|
WCHAR *pszCoMemText;
|
||||||
|
hr = GetAltText( ulStartElement, cElements, ulAlternateIndex,
|
||||||
|
&pszCoMemText, pbDisplayAttributes );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
::CoTaskMemFree( pszCoMemText );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify owners of the alternate committal so that they can adjust
|
||||||
|
// their element offset maps
|
||||||
|
hr = NotifyOwnersOfCommit( ulStartElement, cElements, ulAlternateIndex );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call to ISpPhraseAlt::Commit()
|
||||||
|
hr = m_apLastRequestedPhraseAlts[ulAlternateIndex]->Commit();
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The alternate is now "dead"
|
||||||
|
|
||||||
|
// Re-initialize the phrase replacement info, as the element indices
|
||||||
|
// and text replacment (ITN) situations are likely to have changed
|
||||||
|
return m_pPhraseReplacement->Initialize( *m_cpRecoResult );
|
||||||
|
|
||||||
|
} /* CResultContainer::ChooseAlternate */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CResultContainer::NotifyOwnersOfCommit *
|
||||||
|
*----------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Called when an alternate is about to be committed BEFORE
|
||||||
|
* the commit happens.
|
||||||
|
* Notifies all DictationRuns that hold onto this result
|
||||||
|
* that their phrase element offset maps will need to change
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_OUTOFMEMORY if the head of the owner list wasn't
|
||||||
|
* allocated at construction time
|
||||||
|
* Return value of CResultContainer::GetAlternates()
|
||||||
|
* Return value of CPhraseReplacement::Initialize()
|
||||||
|
* Return value of CResultContainer::GetAltInfo()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CResultContainer::NotifyOwnersOfCommit( ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulAlternateIndex )
|
||||||
|
//ISpPhraseAlt *pChosenAlternate )
|
||||||
|
{
|
||||||
|
if ( !m_pOwnerListHead )
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First make sure we actually have this alternate
|
||||||
|
ULONG cPhrasesReturned;
|
||||||
|
HRESULT hr = GetAlternates(
|
||||||
|
ulStartElement, cElements, ulAlternateIndex + 1, &cPhrasesReturned );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
if ( cPhrasesReturned < (ulAlternateIndex + 1) )
|
||||||
|
{
|
||||||
|
// There aren't enough alternates to accommodate
|
||||||
|
// this one
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check: The pointer to the ISpPhraseAlt for this
|
||||||
|
// alternate is non-NULL
|
||||||
|
_ASSERTE( m_apLastRequestedPhraseAlts[ ulAlternateIndex ] );
|
||||||
|
|
||||||
|
// We need to determine how many post-replacement elements the new
|
||||||
|
// phrase will have, but the alternate has not yet been committed to
|
||||||
|
// m_cpRecoResult, so we need to construct a different CPhraseReplacement
|
||||||
|
// to get that information
|
||||||
|
CPhraseReplacement newPhraseRepl;
|
||||||
|
hr = newPhraseRepl.Initialize( *(m_apLastRequestedPhraseAlts[ ulAlternateIndex ]) );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
ULONG cPostReplElementsAfterCommit = newPhraseRepl.GetNumReplacementElements();
|
||||||
|
|
||||||
|
// Find out which (post-replacement) elements in the parent
|
||||||
|
// this alternate will replace
|
||||||
|
ULONG ulStartInParent;
|
||||||
|
ULONG cEltsInParent;
|
||||||
|
hr = GetAltInfo( ulStartElement, cElements, ulAlternateIndex,
|
||||||
|
&ulStartInParent, &cEltsInParent );
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through the owner list, and let each one adjust its maps
|
||||||
|
for ( OWNERNODE *pNode = m_pOwnerListHead; pNode; pNode = pNode->pNext )
|
||||||
|
{
|
||||||
|
hr = pNode->pOwner->OnAlternateCommit( ulStartInParent,
|
||||||
|
cEltsInParent, cPostReplElementsAfterCommit );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CResultContainer::NotifyOwnersOfCommit */
|
||||||
|
|
119
mp/src/utils/sapi51/Samples/CPP/DictPad/resultcontainer.h
Normal file
119
mp/src/utils/sapi51/Samples/CPP/DictPad/resultcontainer.h
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* resultcontainer.h
|
||||||
|
* This module contains the definition of CResultContainer.
|
||||||
|
* CResultContainer makes all of the recognition-object-
|
||||||
|
* specific SAPI5 calls
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DictationRun.h"
|
||||||
|
|
||||||
|
// Forward definition
|
||||||
|
class CDictationRun;
|
||||||
|
|
||||||
|
// List node for the result container's list of owner DictationRuns
|
||||||
|
typedef struct OWNERNODE
|
||||||
|
{
|
||||||
|
CDictationRun *pOwner;
|
||||||
|
OWNERNODE *pNext;
|
||||||
|
} OWNERNODE;
|
||||||
|
|
||||||
|
// Constant for alternate retrieval
|
||||||
|
#define ALT_REQUEST_COUNT 15
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CResultContainer *
|
||||||
|
*------------------*
|
||||||
|
* Description:
|
||||||
|
* CResultContainer is the class that handles the recognition result
|
||||||
|
* object that corresponds to one or more CDictationRun's (see
|
||||||
|
* DictationRun.h) that hold phrase elements from that result.
|
||||||
|
* All SAPI5 calls on recognition result objects are made from
|
||||||
|
* the appropriate instance of CResultContainer
|
||||||
|
*******************************************************************************/
|
||||||
|
class CResultContainer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CResultContainer( ISpRecoResult &rResult,
|
||||||
|
CDictationRun &rFirstOwner,
|
||||||
|
CPhraseReplacement &rPhraseReplacement );
|
||||||
|
~CResultContainer();
|
||||||
|
|
||||||
|
HRESULT AddOwner( CDictationRun &rNewOwner );
|
||||||
|
void DeleteOwner( CDictationRun &rOldOwner );
|
||||||
|
|
||||||
|
CPhraseReplacement *GetPhraseReplacement()
|
||||||
|
{ return m_pPhraseReplacement; }
|
||||||
|
|
||||||
|
// These methods that behave exactly like the methods of
|
||||||
|
// the same name in ISpRecoResult, except the arguments
|
||||||
|
// to these take into account possible ITN replacement
|
||||||
|
HRESULT SpeakAudio(
|
||||||
|
ULONG ulStartElement,
|
||||||
|
ULONG cElements );
|
||||||
|
HRESULT Serialize(
|
||||||
|
SPSERIALIZEDRESULT **ppResultBlock)
|
||||||
|
{ return m_cpRecoResult->Serialize( ppResultBlock );}
|
||||||
|
|
||||||
|
// These methods are closely related to ISpRecoResult
|
||||||
|
// methods, altered slightly for the purposes of this app
|
||||||
|
HRESULT GetAlternatesText(
|
||||||
|
ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulRequestCount,
|
||||||
|
WCHAR **ppszCoMemText,
|
||||||
|
ULONG *pcPhrasesReturned );
|
||||||
|
HRESULT GetAltInfo(
|
||||||
|
ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulAlternateIndex,
|
||||||
|
ULONG *pulStartInParent,
|
||||||
|
ULONG *pcEltsInParent,
|
||||||
|
ULONG *pcEltsInAlt = NULL,
|
||||||
|
bool fReturnPostReplIndices = true);
|
||||||
|
HRESULT GetAltText(
|
||||||
|
ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulAlternateIndex,
|
||||||
|
WCHAR **ppwszCoMemText,
|
||||||
|
BYTE *pbDisplayAttributes );
|
||||||
|
HRESULT ChooseAlternate(
|
||||||
|
ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulAlternateIndex,
|
||||||
|
BYTE *pbDisplayAttributes );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
HRESULT GetAlternates(
|
||||||
|
ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulRequestCount,
|
||||||
|
ULONG *pcPhrasesReturned );
|
||||||
|
|
||||||
|
// Called whenever the RecoResult has changed as a result of some
|
||||||
|
// owner committing an alternate
|
||||||
|
HRESULT NotifyOwnersOfCommit(
|
||||||
|
ULONG ulStartElement,
|
||||||
|
ULONG cElements,
|
||||||
|
ULONG ulAlternateIndex );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
CComPtr<ISpRecoResult> m_cpRecoResult;
|
||||||
|
CPhraseReplacement *m_pPhraseReplacement;
|
||||||
|
OWNERNODE *m_pOwnerListHead;
|
||||||
|
|
||||||
|
// Information about the last-requested set of alternates.
|
||||||
|
// Note that m_ulStartOfLastRequestedAlts and m_cElementsInLastRequestedAlts
|
||||||
|
// are indices with ITN replacements figured in
|
||||||
|
ISpPhraseAlt * m_apLastRequestedPhraseAlts[ALT_REQUEST_COUNT];
|
||||||
|
ULONG m_cLastRequestedAltsReturned;
|
||||||
|
ULONG m_ulStartOfLastRequestedAlts;
|
||||||
|
ULONG m_cElementsInLastRequestedAlts;
|
||||||
|
}; // class CResultContainer
|
||||||
|
|
||||||
|
|
BIN
mp/src/utils/sapi51/Samples/CPP/DictPad/small.ico
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/DictPad/small.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
9
mp/src/utils/sapi51/Samples/CPP/DictPad/stdafx.cpp
Normal file
9
mp/src/utils/sapi51/Samples/CPP/DictPad/stdafx.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// stdafx.cpp : source file that includes just the standard includes
|
||||||
|
// dictpad.pch will be the pre-compiled header
|
||||||
|
// stdafx.obj will contain the pre-compiled type information
|
||||||
|
//Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
// TODO: reference any additional headers you need in STDAFX.H
|
||||||
|
// and not in this file
|
37
mp/src/utils/sapi51/Samples/CPP/DictPad/stdafx.h
Normal file
37
mp/src/utils/sapi51/Samples/CPP/DictPad/stdafx.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// stdafx.h : include file for standard system include files,
|
||||||
|
// or project specific include files that are used frequently, but
|
||||||
|
// are changed infrequently
|
||||||
|
//
|
||||||
|
|
||||||
|
#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
|
||||||
|
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif // _MSC_VER > 1000
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Windows Header Files:
|
||||||
|
#include <atlbase.h>
|
||||||
|
|
||||||
|
// C RunTime Header Files
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <sapi.h>
|
||||||
|
#include <sphelper.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "tom.h"
|
||||||
|
|
||||||
|
// Local Header Files
|
||||||
|
|
||||||
|
// TODO: reference additional headers your program requires here
|
||||||
|
|
||||||
|
//{{AFX_INSERT_LOCATION}}
|
||||||
|
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||||
|
|
||||||
|
#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
|
559
mp/src/utils/sapi51/Samples/CPP/DictPad/textrun.cpp
Normal file
559
mp/src/utils/sapi51/Samples/CPP/DictPad/textrun.cpp
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* textrun.cpp
|
||||||
|
* Implementation details for the CTextRun object which is our base class
|
||||||
|
* for tracking all the text (be it dictated or typed) in our product.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "textrun.h"
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::CTextRun *
|
||||||
|
*--------------------*
|
||||||
|
* Description:
|
||||||
|
* CTextRun constructor
|
||||||
|
**********************************************************************/
|
||||||
|
CTextRun::CTextRun() : m_cpTextRange( NULL ),
|
||||||
|
m_dwRefCount( NULL )
|
||||||
|
{
|
||||||
|
} /* CTextRun::CTextRun */
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::~CTextRun *
|
||||||
|
*---------------------*
|
||||||
|
* Description:
|
||||||
|
* CTextRun destructor
|
||||||
|
**********************************************************************/
|
||||||
|
CTextRun::~CTextRun()
|
||||||
|
{
|
||||||
|
} /* CTextRun::~CTextRun */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::IncrementCount *
|
||||||
|
*--------------------------*
|
||||||
|
* Description:
|
||||||
|
* Increments a reference count on this text run.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* The current count
|
||||||
|
**********************************************************************/
|
||||||
|
DWORD CTextRun::IncrementCount()
|
||||||
|
{
|
||||||
|
m_dwRefCount++;
|
||||||
|
return m_dwRefCount;
|
||||||
|
} /* CTextRun::IncrementCount */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::DecrementCount *
|
||||||
|
*--------------------------*
|
||||||
|
* Description:
|
||||||
|
* Decrements a reference count on this text run. If the
|
||||||
|
* count drops to zero, the text run is deleted.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* The current count
|
||||||
|
**********************************************************************/
|
||||||
|
DWORD CTextRun::DecrementCount()
|
||||||
|
{
|
||||||
|
_ASSERTE( m_dwRefCount );
|
||||||
|
|
||||||
|
DWORD dwRefCount = --m_dwRefCount;
|
||||||
|
if( !m_dwRefCount )
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
return dwRefCount;
|
||||||
|
} /* CTextRun::DecrementCount */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CTextRun::SetTextRange *
|
||||||
|
*------------------------*
|
||||||
|
* Description:
|
||||||
|
* Stores the text range interface pointer for this run
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_POINTER if pTextRange is NULL
|
||||||
|
******************************************************************************/
|
||||||
|
HRESULT CTextRun::SetTextRange( ITextRange *pTextRange )
|
||||||
|
{
|
||||||
|
if ( !pTextRange )
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cpTextRange = pTextRange;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CTextRun::SetTextRange */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::Split *
|
||||||
|
*-----------------*
|
||||||
|
* Description:
|
||||||
|
* Splits up a TextRun so that this text run now ends at lFirstEnd
|
||||||
|
* and the second text run begins at lSecondBegin.
|
||||||
|
* "This" will now be a shorter range (it will end sooner),
|
||||||
|
* and *ppTextRun will point to the new text run
|
||||||
|
* (space will be allocated here for *ppTextRun)
|
||||||
|
* to be inserted in the list.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_INVALIDARG
|
||||||
|
* E_OUTOFMEMORY
|
||||||
|
* Return value of ITextDocument::Range()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CTextRun::Split( long *plFirstEnd, long *plSecondBegin,
|
||||||
|
ITextDocument *cpTextDoc,
|
||||||
|
CTextRun **ppTextRun )
|
||||||
|
{
|
||||||
|
if ( !plFirstEnd || !plSecondBegin || !cpTextDoc || !ppTextRun )
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
_ASSERTE( m_cpTextRange );
|
||||||
|
if ( !m_cpTextRange )
|
||||||
|
{
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These values won't be changing, since this run has no associated
|
||||||
|
// RecoResult.
|
||||||
|
// We can chop this block right at these positions.
|
||||||
|
long lFirstEnd = *plFirstEnd;
|
||||||
|
long lSecondBegin = *plSecondBegin;
|
||||||
|
|
||||||
|
if ( !WithinRange( lFirstEnd ) || (lFirstEnd > lSecondBegin) )
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (GetStart() == lSecondBegin) || (GetEnd() == lFirstEnd) || (lSecondBegin > GetEnd()) )
|
||||||
|
{
|
||||||
|
// Don't need to do anything, since we are asking for both of the
|
||||||
|
// cuts to be made on already-existing TextRun boundaries
|
||||||
|
*ppTextRun = NULL;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppTextRun = new CTextRun();
|
||||||
|
if ( !(*ppTextRun) )
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The latter range will start at lSecondBegin and end where "this" ended
|
||||||
|
long lEnd = GetEnd();
|
||||||
|
CComPtr<ITextRange> pLatterRange;
|
||||||
|
HRESULT hr = cpTextDoc->Range( lSecondBegin, lEnd, &pLatterRange );
|
||||||
|
if ( FAILED( hr ) )
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
(*ppTextRun)->SetTextRange( pLatterRange );
|
||||||
|
|
||||||
|
// Adjust the end of "this"'s range; it will end at lFirstEnd
|
||||||
|
m_cpTextRange->SetEnd( lFirstEnd );
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
} /* CTextRun::Split */
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::Concatenate *
|
||||||
|
*-----------------------*
|
||||||
|
* Description:
|
||||||
|
* If possible, concatenates pNext (pPrev if fConcatAfter is false)
|
||||||
|
* onto the end of this.
|
||||||
|
* Another CTextRun can always be concatenated on, unless it
|
||||||
|
* contains dictation.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* E_NOMERGE if could not be merged (because pTextRun is dictation)
|
||||||
|
* E_FULLMERGE
|
||||||
|
**********************************************************************/
|
||||||
|
MERGERESULT CTextRun::Concatenate( CTextRun *pTextRun, bool fConcatAfter )
|
||||||
|
{
|
||||||
|
if ( !pTextRun || !m_cpTextRange )
|
||||||
|
{
|
||||||
|
return E_NOMERGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for compatibility: In this case, neither mergee can be
|
||||||
|
// a dict run
|
||||||
|
if ( IsDict() || pTextRun->IsDict() )
|
||||||
|
{
|
||||||
|
return E_NOMERGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lNewBound will be the new end (resp. start) of the run, if the
|
||||||
|
// concatenation is successful
|
||||||
|
long lNewBound;
|
||||||
|
|
||||||
|
// Concatenation is possible iff one run ends exactly where the other
|
||||||
|
// begins.
|
||||||
|
// If concatenation is possible, do it.
|
||||||
|
if ( fConcatAfter )
|
||||||
|
{
|
||||||
|
// Will be concatenating pTextRun onto the end of this
|
||||||
|
if ( GetEnd() != pTextRun->GetStart() )
|
||||||
|
{
|
||||||
|
// They are not consecutive runs
|
||||||
|
return E_NOMERGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lNewBound will be the new end of the run, if the
|
||||||
|
// concatenation is successful
|
||||||
|
lNewBound = pTextRun->GetEnd();
|
||||||
|
|
||||||
|
// Swallow up pTextRun by setting our end to its end
|
||||||
|
SetEnd( lNewBound );
|
||||||
|
|
||||||
|
// Make pTextRun degenerate
|
||||||
|
pTextRun->SetStart( lNewBound );
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Will be concatenating pTextRun onto the beginning of this
|
||||||
|
if ( GetStart() != pTextRun->GetEnd() )
|
||||||
|
{
|
||||||
|
return E_NOMERGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lNewBound will be the new start of the run, if the
|
||||||
|
// concatenation is successful
|
||||||
|
lNewBound = pTextRun->GetStart();
|
||||||
|
|
||||||
|
// Swallow up pTextRun by setting our start to its start
|
||||||
|
SetStart( lNewBound );
|
||||||
|
|
||||||
|
// Make pTextRun degenerate
|
||||||
|
pTextRun->SetEnd( lNewBound );
|
||||||
|
}
|
||||||
|
|
||||||
|
return E_FULLMERGE;
|
||||||
|
} /* CTextRun::Concatenate */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::Speak *
|
||||||
|
*-----------------*
|
||||||
|
* Description:
|
||||||
|
* Speaks the text associated with this CTextRun using TTS.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* Return value of ITextRange::GetText()
|
||||||
|
* Return value of ISpVoice::Speak()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CTextRun::Speak( ISpVoice &rVoice )
|
||||||
|
{
|
||||||
|
_ASSERTE( m_cpTextRange );
|
||||||
|
if ( !m_cpTextRange )
|
||||||
|
{
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the text and speak it.
|
||||||
|
BSTR bstrText;
|
||||||
|
HRESULT hr = m_cpTextRange->GetText( &bstrText );
|
||||||
|
if( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
hr = rVoice.Speak( bstrText, SPF_ASYNC, NULL );
|
||||||
|
|
||||||
|
::SysFreeString( bstrText );
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
} /* CTextRun::Speak */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::Speak() *
|
||||||
|
*-------------------*
|
||||||
|
* Description:
|
||||||
|
* Uses *plStart and *plEnd to find the nearest start and
|
||||||
|
* endpoints for speaking (to the nearest word).
|
||||||
|
* Returns these values in plStart and plEnd.
|
||||||
|
* Speaks the text associated with this CTextRun from *plStart
|
||||||
|
* to *plEnd.
|
||||||
|
*
|
||||||
|
* If *plStart is not within the range, then
|
||||||
|
* start at the beginning. If lEnd is not within range, then
|
||||||
|
* end at the end.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_POINTER
|
||||||
|
* Return value of CTextRun::Speak()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CTextRun::Speak( ISpVoice &rVoice,
|
||||||
|
long *plStart,
|
||||||
|
long *plEnd )
|
||||||
|
{
|
||||||
|
if ( !plStart || !plEnd )
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
_ASSERTE( m_cpTextRange );
|
||||||
|
if ( !m_cpTextRange )
|
||||||
|
{
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the old range
|
||||||
|
long lOldStart = GetStart();
|
||||||
|
long lOldEnd = GetEnd();
|
||||||
|
|
||||||
|
// Out of range start or end means we start speaking from the start
|
||||||
|
// or end (resp.) of the text range.
|
||||||
|
|
||||||
|
if ( WithinRange( *plStart ) )
|
||||||
|
{
|
||||||
|
// The start needs to be moved
|
||||||
|
SetStart( *plStart );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*plStart = GetStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( WithinRange( *plEnd ) )
|
||||||
|
{
|
||||||
|
// The end needs to be moved
|
||||||
|
SetEnd( *plEnd );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*plEnd = GetEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand to include whole words
|
||||||
|
m_cpTextRange->Expand( tomWord, NULL );
|
||||||
|
|
||||||
|
// Get the new start and end so that we can pass them back
|
||||||
|
m_cpTextRange->GetStart( plStart );
|
||||||
|
m_cpTextRange->GetEnd( plEnd );
|
||||||
|
|
||||||
|
// We should never speak past the end of this run, even if expanding to include
|
||||||
|
// whole words caused extra text to be included
|
||||||
|
// (e.g. if you typed "This is a sentence" and dictated some text that
|
||||||
|
// consumed leading spaces right afterwards)
|
||||||
|
*plStart = __max( *plStart, lOldStart );
|
||||||
|
*plEnd = __min( *plEnd, lOldEnd );
|
||||||
|
SetStart( *plStart );
|
||||||
|
SetEnd( *plEnd );
|
||||||
|
|
||||||
|
// Pass to the CTextRun::Speak() that speaks an entire run
|
||||||
|
HRESULT hr = Speak( rVoice );
|
||||||
|
|
||||||
|
// Restore the old range limits
|
||||||
|
SetStart( lOldStart );
|
||||||
|
SetEnd( lOldEnd );
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
} /* CTextRun::Speak */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::Serialize *
|
||||||
|
*---------------------*
|
||||||
|
* Description:
|
||||||
|
* Serializes the text for this run.
|
||||||
|
* Simply writes a small header that contains the start
|
||||||
|
* and end indices of this run and indicates that
|
||||||
|
* no phrase blob follows.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_INVALIDARG
|
||||||
|
* E_UNEXPECTED
|
||||||
|
* Return value of ISequentialStream::Write()
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CTextRun::Serialize( IStream *pStream, ISpRecoContext *pRecoCtxt )
|
||||||
|
{
|
||||||
|
if ( !pStream )
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
_ASSERTE( m_cpTextRange );
|
||||||
|
if ( !m_cpTextRange )
|
||||||
|
{
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNHEADER runHdr;
|
||||||
|
runHdr.lStart = GetStart();
|
||||||
|
runHdr.lEnd = GetEnd();
|
||||||
|
runHdr.bResultFollows = false;
|
||||||
|
|
||||||
|
// Write the header to the stream
|
||||||
|
ULONG cbWritten;
|
||||||
|
HRESULT hr = pStream->Write( &runHdr, sizeof( RUNHEADER ), &cbWritten );
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
} /* CTextRun::Serialize */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::IsConsumeLeadingSpaces *
|
||||||
|
*----------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Sets *pfConsumeLeadingSpaces to true iff leading spaces before
|
||||||
|
* lPos would need to be consumed.
|
||||||
|
* For a text run this value will always be false, since
|
||||||
|
* typed text has no "display attributes"
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_POINTER
|
||||||
|
* E_INVALIDARG if lPos is out of range
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CTextRun::IsConsumeLeadingSpaces( const long lPos,
|
||||||
|
bool *pfConsumeLeadingSpaces )
|
||||||
|
{
|
||||||
|
if ( !pfConsumeLeadingSpaces )
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
if ( !WithinRange( lPos ) )
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pfConsumeLeadingSpaces = false;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CTextRun::IsConsumeLeadingSpaces */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::HowManySpacesAfter *
|
||||||
|
*------------------------------*
|
||||||
|
* Description:
|
||||||
|
* Returns the number of spaces that would need to precede text
|
||||||
|
* if text were to be inserted at position lPos.
|
||||||
|
* This number is in the out param puiSpaces.
|
||||||
|
* For a text run this value will always be zero, since
|
||||||
|
* typed text has no "display attributes"
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* E_POINTER
|
||||||
|
* E_INVALIDARG if lPos is out of range
|
||||||
|
**********************************************************************/
|
||||||
|
HRESULT CTextRun::HowManySpacesAfter( const long lPos, UINT *puiSpaces )
|
||||||
|
{
|
||||||
|
if ( !puiSpaces )
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
if ( !WithinRange( lPos ) )
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
*puiSpaces = 0;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
} /* CTextRun::HowManySpacesAfter */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::GetStart *
|
||||||
|
*--------------------*
|
||||||
|
* Description:
|
||||||
|
* Returns the start of the associated TextRange, -1 in case
|
||||||
|
* of error.
|
||||||
|
**********************************************************************/
|
||||||
|
long CTextRun::GetStart()
|
||||||
|
{
|
||||||
|
if ( !m_cpTextRange )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lRet;
|
||||||
|
HRESULT hr = m_cpTextRange->GetStart( &lRet );
|
||||||
|
|
||||||
|
return (SUCCEEDED( hr )) ? lRet : -1;
|
||||||
|
} /* CTextRun::GetStart */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::SetStart *
|
||||||
|
*--------------------*
|
||||||
|
* Description:
|
||||||
|
* Sets the start of the associated TextRange.
|
||||||
|
**********************************************************************/
|
||||||
|
void CTextRun::SetStart( long lStart )
|
||||||
|
{
|
||||||
|
m_cpTextRange->SetStart( lStart );
|
||||||
|
} /* CTextRun::SetStart */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::GetEnd *
|
||||||
|
*------------------*
|
||||||
|
* Description:
|
||||||
|
* Returns the end of the associated TextRange, -1 in case
|
||||||
|
* of error.
|
||||||
|
**********************************************************************/
|
||||||
|
long CTextRun::GetEnd()
|
||||||
|
{
|
||||||
|
if ( !m_cpTextRange )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lRet;
|
||||||
|
HRESULT hr = m_cpTextRange->GetEnd( &lRet );
|
||||||
|
|
||||||
|
return (SUCCEEDED( hr )) ? lRet : -1;
|
||||||
|
} /* CTextRun::GetEnd */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CTextRun::SetEnd *
|
||||||
|
*------------------*
|
||||||
|
* Description:
|
||||||
|
* Sets the end of the associated TextRange
|
||||||
|
**********************************************************************/
|
||||||
|
void CTextRun::SetEnd( long lEnd )
|
||||||
|
{
|
||||||
|
m_cpTextRange->SetEnd( lEnd );
|
||||||
|
} /* CTextRun::SetEnd */
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* CTextRun::WithinRange *
|
||||||
|
*-----------------------*
|
||||||
|
* Description:
|
||||||
|
* Determines whether lCursorPos falls within the range of
|
||||||
|
* this CTextRun.
|
||||||
|
* Return:
|
||||||
|
* true iff RunStart <= lCursorPos < RunEnd
|
||||||
|
**********************************************************************/
|
||||||
|
bool CTextRun::WithinRange( long lCursorPos )
|
||||||
|
{
|
||||||
|
if ( !m_cpTextRange )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lStart= -1;
|
||||||
|
long lEnd= -1;
|
||||||
|
|
||||||
|
HRESULT hr = m_cpTextRange->GetStart( &lStart );
|
||||||
|
if ( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
hr = m_cpTextRange->GetEnd( &lEnd );
|
||||||
|
}
|
||||||
|
|
||||||
|
return (SUCCEEDED( hr ) && ( lCursorPos >= lStart ) && ( lCursorPos <= lEnd ));
|
||||||
|
} /* CTextRun::WithinRange */
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* CTextRun::IsDegenerate *
|
||||||
|
*------------------------*
|
||||||
|
* Description:
|
||||||
|
* Determines whether "this" has a degenerate range associated
|
||||||
|
* with it.
|
||||||
|
* Return:
|
||||||
|
* true iff start == end
|
||||||
|
**********************************************************************/
|
||||||
|
bool CTextRun::IsDegenerate()
|
||||||
|
{
|
||||||
|
return ( GetStart() == GetEnd() );
|
||||||
|
} /* CTextRun::IsDegenerate */
|
90
mp/src/utils/sapi51/Samples/CPP/DictPad/textrun.h
Normal file
90
mp/src/utils/sapi51/Samples/CPP/DictPad/textrun.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* textrun.h
|
||||||
|
* This module contains the definition support for CTextRun which is
|
||||||
|
* our base class for holding onto all the text with DictPad.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Enumerated return type for CTextRun merging functions
|
||||||
|
typedef enum MERGERESULT
|
||||||
|
{
|
||||||
|
E_NOMERGE, // No merging could be done at all
|
||||||
|
E_PARTIALMERGE, // Part but not all of the range could be merged in
|
||||||
|
E_LESSTEXT, // Some of the range had to be given up
|
||||||
|
E_FULLMERGE // All of the range was merged
|
||||||
|
};
|
||||||
|
|
||||||
|
// Header for serialized CTextRuns
|
||||||
|
typedef struct RUNHEADER
|
||||||
|
{
|
||||||
|
bool bResultFollows; // true iff this is a dictation run with the
|
||||||
|
// associated reco result following in the stream
|
||||||
|
long lStart; // Start index of the associated text
|
||||||
|
long lEnd; // End index of the associated text
|
||||||
|
} RUNHEADER;
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CTextRun *
|
||||||
|
*----------*
|
||||||
|
* Description:
|
||||||
|
* This class handles a consecutive run of text in the document.
|
||||||
|
********************************************************************************/
|
||||||
|
class CTextRun
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor / destructor
|
||||||
|
CTextRun();
|
||||||
|
virtual ~CTextRun();
|
||||||
|
|
||||||
|
// Refcounting methods
|
||||||
|
DWORD IncrementCount();
|
||||||
|
DWORD DecrementCount();
|
||||||
|
|
||||||
|
// Initialization method
|
||||||
|
virtual HRESULT SetTextRange( ITextRange *pTextRange );
|
||||||
|
|
||||||
|
// Phrase element-related methods
|
||||||
|
virtual HRESULT Split( long *plFirstEnd, long *plSecondBegin,
|
||||||
|
ITextDocument *cpTextDoc, CTextRun **ppTextRun );
|
||||||
|
virtual MERGERESULT Concatenate( CTextRun *pTextRun, bool bConcatAfter );
|
||||||
|
virtual HRESULT CorrectPhraseEltsAndRange( bool bForward, bool *pfCorrectionResult = NULL )
|
||||||
|
{
|
||||||
|
if ( pfCorrectionResult )
|
||||||
|
{
|
||||||
|
*pfCorrectionResult = true;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Playback methods
|
||||||
|
virtual HRESULT Speak( ISpVoice &rVoice ); // Speak a whole block
|
||||||
|
virtual HRESULT Speak( ISpVoice &rVoice, long *plStart, long *plEnd );
|
||||||
|
// Speak part of a block
|
||||||
|
|
||||||
|
// Serialization method
|
||||||
|
virtual HRESULT Serialize( IStream *pStream, ISpRecoContext *pRecoCtxt = NULL );
|
||||||
|
// Serialize and write to stream
|
||||||
|
|
||||||
|
// Display attributes methods
|
||||||
|
virtual HRESULT IsConsumeLeadingSpaces( const long lPos, bool *pfConsumeLeadingSpaces );
|
||||||
|
virtual HRESULT HowManySpacesAfter( const long lPos, UINT *puiSpaces );
|
||||||
|
|
||||||
|
virtual bool IsDict() { return FALSE; };
|
||||||
|
|
||||||
|
// Endpoints-related methods
|
||||||
|
long GetStart();
|
||||||
|
void SetStart( long lStart );
|
||||||
|
long GetEnd();
|
||||||
|
void SetEnd( long lEnd );
|
||||||
|
bool WithinRange( long lCursorPos );
|
||||||
|
bool IsDegenerate();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CComPtr<ITextRange> m_cpTextRange;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DWORD m_dwRefCount;
|
||||||
|
}; /* class CTextRun */
|
||||||
|
|
1596
mp/src/utils/sapi51/Samples/CPP/DictPad/textrunlist.cpp
Normal file
1596
mp/src/utils/sapi51/Samples/CPP/DictPad/textrunlist.cpp
Normal file
File diff suppressed because it is too large
Load Diff
101
mp/src/utils/sapi51/Samples/CPP/DictPad/textrunlist.h
Normal file
101
mp/src/utils/sapi51/Samples/CPP/DictPad/textrunlist.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* TextRunList.h
|
||||||
|
* This module contains the definition details of CTextRunList which is
|
||||||
|
* a container class that keeps track of all of the individual text runs
|
||||||
|
* in DictPad
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TextRun.h"
|
||||||
|
#include "DictationRun.h"
|
||||||
|
|
||||||
|
// Nodes for the CTextRunList
|
||||||
|
typedef struct TEXTRUNNODE
|
||||||
|
{
|
||||||
|
CTextRun *pTextRun; // Points to the actual test run information
|
||||||
|
struct TEXTRUNNODE *pPrev; // Points to the previous node in our list
|
||||||
|
struct TEXTRUNNODE *pNext; // Points to the next node in our list
|
||||||
|
} TEXTRUNNODE, *PTEXTRUNNODE;
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CTextRunList
|
||||||
|
* This class keeps track of all the CTextRun objects that exist to
|
||||||
|
* represent the entire document being edited within DictPad
|
||||||
|
******************************************************************************/
|
||||||
|
class CTextRunList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor/destructor
|
||||||
|
CTextRunList( ITextDocument *pTextDoc = NULL);
|
||||||
|
~CTextRunList();
|
||||||
|
|
||||||
|
// Initialization methods
|
||||||
|
void SetTextDoc( ITextDocument *cpTextDoc ) { m_cpTextDoc = cpTextDoc; }
|
||||||
|
HRESULT CreateSimpleList(); // Create a one-node list consisting of a single TextRun
|
||||||
|
|
||||||
|
// Method for new text
|
||||||
|
HRESULT Insert( CTextRun *pTextRun ); // Takes care of figuring out where the new node should go
|
||||||
|
|
||||||
|
// Playback method
|
||||||
|
HRESULT Speak( ISpVoice &rVoice, long *plStartSpeaking, long *plEndSpeaking );
|
||||||
|
// Speak starting and ending at specified locations
|
||||||
|
|
||||||
|
// Serialization methods
|
||||||
|
HRESULT Serialize( IStream *pStream, ISpRecoContext *pRecoCtxt );
|
||||||
|
// Write the contents of the TextRunList to pStream
|
||||||
|
HRESULT Deserialize( IStream *pStream, ISpRecoContext *pRecoCtxt );
|
||||||
|
// Recreate the TextRunList from the stream
|
||||||
|
|
||||||
|
// Display attributes methods
|
||||||
|
HRESULT IsConsumeLeadingSpaces( long lPos, bool *pfConsumeLeadingSpaces );
|
||||||
|
HRESULT HowManySpacesAfter( long lPos, UINT *puiSpaces );
|
||||||
|
// How many spaces would need to precede text
|
||||||
|
// that would start at lPos
|
||||||
|
|
||||||
|
// Methods that deal with positions in the text
|
||||||
|
long GetTailEnd(); // length of the document
|
||||||
|
PTEXTRUNNODE Find( long lDest ); // Pointer to the node that contains this position
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Methods for manipulation of adjacent CTextRuns
|
||||||
|
HRESULT MoveCurrentTo( LONG lDest ); // Move m_pCurrent to a node that ends at
|
||||||
|
// lDest, splitting nodes if necessary
|
||||||
|
HRESULT SplitNode( PTEXTRUNNODE pNode ); // Split the given node for m_pNodeToInsert
|
||||||
|
HRESULT MergeIn( PTEXTRUNNODE pNode, bool *pfNodeMadeItIn );
|
||||||
|
// Try to merge a new node in with neighbors
|
||||||
|
HRESULT MergeInDictRun( PTEXTRUNNODE pNode );
|
||||||
|
// Handle newly-dictated text in the list
|
||||||
|
|
||||||
|
// List manipulation methods
|
||||||
|
HRESULT InsertAfter( PTEXTRUNNODE pCurrent, PTEXTRUNNODE pNodeToInsert );
|
||||||
|
HRESULT RemoveNode( PTEXTRUNNODE pNode );
|
||||||
|
HRESULT AddHead( PTEXTRUNNODE pHead );
|
||||||
|
HRESULT AddTail( PTEXTRUNNODE pTail );
|
||||||
|
void RemoveHead();
|
||||||
|
void RemoveTail();
|
||||||
|
|
||||||
|
// Clean-up method
|
||||||
|
void DeleteAllNodes();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// These cached nodes help us to add new nodes to our list
|
||||||
|
// somewhat optimally.
|
||||||
|
PTEXTRUNNODE m_pHead; // Starting point (necessary reguardless of strategy)
|
||||||
|
PTEXTRUNNODE m_pTail; // Last node in our list
|
||||||
|
PTEXTRUNNODE m_pCurrent; // Most recently added node. We cache this one under the
|
||||||
|
// assumption that nodes will often be added in groups;
|
||||||
|
// remembering where the last one went is a good clue
|
||||||
|
// as to where we should insert the next one.
|
||||||
|
|
||||||
|
PTEXTRUNNODE m_pNodeToInsert;
|
||||||
|
// Node that we are about to add. This information is necessary for
|
||||||
|
// calling CTextRun::Split()
|
||||||
|
|
||||||
|
CComPtr<ITextDocument> m_cpTextDoc; // Pointer to the ITextDocument interface to which
|
||||||
|
// we will need access for splitting nodes in order
|
||||||
|
// to retrieve ITextRange pointers.
|
||||||
|
}; /* class CTextRunList */
|
||||||
|
|
6612
mp/src/utils/sapi51/Samples/CPP/DictPad/tom.h
Normal file
6612
mp/src/utils/sapi51/Samples/CPP/DictPad/tom.h
Normal file
File diff suppressed because it is too large
Load Diff
BIN
mp/src/utils/sapi51/Samples/CPP/DictPad/toolbar1.bmp
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/DictPad/toolbar1.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 886 B |
44
mp/src/utils/sapi51/Samples/CPP/DictPad/version.rc2
Normal file
44
mp/src/utils/sapi51/Samples/CPP/DictPad/version.rc2
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef _MAC
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,0,1
|
||||||
|
PRODUCTVERSION 1,0,0,1
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x1L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Comments", "\0"
|
||||||
|
VALUE "CompanyName", "Microsoft Corp.\0"
|
||||||
|
VALUE "FileDescription", "Dictation Pad Sample\0"
|
||||||
|
VALUE "FileVersion", "1, 0, 0, 1\0"
|
||||||
|
VALUE "InternalName", "DICTPAD\0"
|
||||||
|
VALUE "LegalCopyright", "Copyright (c) Microsoft Corporation. All rights reserved.\0"
|
||||||
|
VALUE "LegalTrademarks", "\0"
|
||||||
|
VALUE "OriginalFilename", "dictpad.exe\0"
|
||||||
|
VALUE "PrivateBuild", "\0"
|
||||||
|
VALUE "ProductName", "Microsoft Corp. SAPI5 samples\0"
|
||||||
|
VALUE "ProductVersion", "1, 0, 0, 1\0"
|
||||||
|
VALUE "SpecialBuild", "\0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // !_MAC
|
20
mp/src/utils/sapi51/Samples/CPP/Engines/SR/resource.h
Normal file
20
mp/src/utils/sapi51/Samples/CPP/Engines/SR/resource.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Developer Studio generated include file.
|
||||||
|
// Used by sreng.rc
|
||||||
|
//
|
||||||
|
#define IDS_PROJNAME 100
|
||||||
|
#define IDR_SRENG 101
|
||||||
|
#define IDR_SRENGUI 102
|
||||||
|
#define IDR_SRENGEXT 103
|
||||||
|
#define IDR_SRENGALT 104
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 201
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 32768
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 201
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 103
|
||||||
|
#endif
|
||||||
|
#endif
|
90
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.cpp
Normal file
90
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// srengdll.cpp : Implementation of DLL Exports.
|
||||||
|
//Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
// Note: Proxy/Stub Information
|
||||||
|
// To build a separate proxy/stub DLL,
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include <initguid.h>
|
||||||
|
#include "sreng.h"
|
||||||
|
|
||||||
|
#include "sreng_i.c"
|
||||||
|
#include "sreng.h"
|
||||||
|
#include "srengobj.h"
|
||||||
|
#include "srengui.h"
|
||||||
|
#include "srengext.h"
|
||||||
|
#include "srengalt.h"
|
||||||
|
|
||||||
|
CComModule _Module;
|
||||||
|
|
||||||
|
BEGIN_OBJECT_MAP(ObjectMap)
|
||||||
|
OBJECT_ENTRY(CLSID_SampleSREngine, CSrEngine)
|
||||||
|
OBJECT_ENTRY(CLSID_SampleSREngineUI, CSrEngineUI)
|
||||||
|
OBJECT_ENTRY(CLSID_SampleSRExtension, CSampleSRExtension)
|
||||||
|
OBJECT_ENTRY(CLSID_SampleSREngineAlternates, CSrEngineAlternates)
|
||||||
|
END_OBJECT_MAP()
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DLL Entry Point
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
extern "C"
|
||||||
|
BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||||
|
{
|
||||||
|
if (dwReason == DLL_PROCESS_ATTACH)
|
||||||
|
{
|
||||||
|
_Module.Init(ObjectMap, (HINSTANCE)hInstance, &LIBID_SRENGLib);
|
||||||
|
}
|
||||||
|
else if (dwReason == DLL_PROCESS_DETACH)
|
||||||
|
_Module.Term();
|
||||||
|
return TRUE; // ok
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
extern "C"
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||||
|
{
|
||||||
|
if (dwReason == DLL_PROCESS_ATTACH)
|
||||||
|
{
|
||||||
|
_Module.Init(ObjectMap, hInstance, &LIBID_SRENGLib);
|
||||||
|
DisableThreadLibraryCalls(hInstance);
|
||||||
|
}
|
||||||
|
else if (dwReason == DLL_PROCESS_DETACH)
|
||||||
|
_Module.Term();
|
||||||
|
return TRUE; // ok
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Used to determine whether the DLL can be unloaded by OLE
|
||||||
|
|
||||||
|
STDAPI DllCanUnloadNow(void)
|
||||||
|
{
|
||||||
|
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Returns a class factory to create an object of the requested type
|
||||||
|
|
||||||
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
||||||
|
{
|
||||||
|
return _Module.GetClassObject(rclsid, riid, ppv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DllRegisterServer - Adds entries to the system registry
|
||||||
|
|
||||||
|
STDAPI DllRegisterServer(void)
|
||||||
|
{
|
||||||
|
// registers object, typelib and all interfaces in typelib
|
||||||
|
return _Module.RegisterServer(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DllUnregisterServer - Removes entries from the system registry
|
||||||
|
|
||||||
|
STDAPI DllUnregisterServer(void)
|
||||||
|
{
|
||||||
|
return _Module.UnregisterServer(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
9
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.def
Normal file
9
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.def
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
; sreng.def : Declares the module parameters.
|
||||||
|
|
||||||
|
LIBRARY "sreng.DLL"
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
DllCanUnloadNow PRIVATE
|
||||||
|
DllGetClassObject PRIVATE
|
||||||
|
DllRegisterServer PRIVATE
|
||||||
|
DllUnregisterServer PRIVATE
|
207
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.dsp
Normal file
207
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.dsp
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="sreng" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
|
||||||
|
CFG=sreng - Win32 Release x86
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "sreng.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "sreng.mak" CFG="sreng - Win32 Release x86"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "sreng - Win32 Debug x86" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "sreng - Win32 Release x86" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath "Desktop"
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "sreng - Win32 Debug x86"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "sreng___Win32_Debug_x86"
|
||||||
|
# PROP BASE Intermediate_Dir "sreng___Win32_Debug_x86"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug_x86"
|
||||||
|
# PROP Intermediate_Dir "Debug_x86"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /ZI /Od /I "..\..\sdk\include" /I "..\..\ddk\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_STATIC_REGISTRY" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "..\..\sdk\include" /I "..\..\ddk\include" /I "..\..\..\..\include" /I "..\..\..\..\..\ddk\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_STATIC_REGISTRY" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\sdk\lib\i386"
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\i386"
|
||||||
|
# Begin Custom Build - Performing registration
|
||||||
|
OutDir=.\Debug_x86
|
||||||
|
TargetPath=.\Debug_x86\sreng.dll
|
||||||
|
InputPath=.\Debug_x86\sreng.dll
|
||||||
|
SOURCE="$(InputPath)"
|
||||||
|
|
||||||
|
"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
regsvr32 /s /c "$(TargetPath)"
|
||||||
|
echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "sreng - Win32 Release x86"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "sreng___Win32_Release_x86"
|
||||||
|
# PROP BASE Intermediate_Dir "sreng___Win32_Release_x86"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Release_x86"
|
||||||
|
# PROP Intermediate_Dir "Release_x86"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /ZI /Od /I "..\..\sdk\include" /I "..\..\ddk\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_STATIC_REGISTRY" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MTd /W3 /Gm /Zi /O2 /I "..\..\..\..\include" /I "..\..\..\..\..\ddk\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_STATIC_REGISTRY" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\sdk\lib\i386"
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\i386"
|
||||||
|
# Begin Custom Build - Performing registration
|
||||||
|
OutDir=.\Release_x86
|
||||||
|
TargetPath=.\Release_x86\sreng.dll
|
||||||
|
InputPath=.\Release_x86\sreng.dll
|
||||||
|
SOURCE="$(InputPath)"
|
||||||
|
|
||||||
|
"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||||
|
regsvr32 /s /c "$(TargetPath)"
|
||||||
|
echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
|
||||||
|
|
||||||
|
# End Custom Build
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "sreng - Win32 Debug x86"
|
||||||
|
# Name "sreng - Win32 Release x86"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sreng.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sreng.def
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sreng.idl
|
||||||
|
# ADD BASE MTL /I "..\..\sdk\idl" /tlb ".\sreng.tlb" /h "sreng.h" /iid "sreng_i.c" /Oicf
|
||||||
|
# ADD MTL /I "..\..\..\..\idl" /I "..\..\..\..\..\ddk\idl" /tlb ".\sreng.tlb" /h "sreng.h" /iid "sreng_i.c" /Oicf
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sreng.rc
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengalt.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengext.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengobj.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengui.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\StdAfx.cpp
|
||||||
|
# ADD BASE CPP /Yc"stdafx.h"
|
||||||
|
# ADD CPP /Yc"stdafx.h"
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Resource.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sreng.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengalt.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengext.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengobj.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengui.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\StdAfx.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sreng.rgs
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengalt.rgs
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengext.rgs
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\srengui.rgs
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
64
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.idl
Normal file
64
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.idl
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// srengdll.idl : IDL source for sreng.dll
|
||||||
|
//
|
||||||
|
|
||||||
|
// This file will be processed by the MIDL tool to
|
||||||
|
// produce the type library (sreng.tlb) and marshalling code.
|
||||||
|
|
||||||
|
import "oaidl.idl";
|
||||||
|
import "ocidl.idl";
|
||||||
|
import "sapiddk.idl";
|
||||||
|
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(BBC18F3B-CF35-4f7c-99E8-D1F803AB4851),
|
||||||
|
helpstring("ISampleSRExtension Interface"),
|
||||||
|
pointer_default(unique)
|
||||||
|
]
|
||||||
|
interface ISampleSRExtension : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT ExamplePrivateEngineCall(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(41B89B6C-9399-11D2-9623-00C04F8EE628),
|
||||||
|
version(1.0),
|
||||||
|
helpstring("sreng 1.0 Type Library")
|
||||||
|
]
|
||||||
|
library SRENGLib
|
||||||
|
{
|
||||||
|
importlib("stdole32.tlb");
|
||||||
|
importlib("stdole2.tlb");
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(41B89B79-9399-11D2-9623-00C04F8EE628),
|
||||||
|
helpstring("Sample SR Engine Class")
|
||||||
|
]
|
||||||
|
coclass SampleSREngine
|
||||||
|
{
|
||||||
|
[default] interface ISpSREngine;
|
||||||
|
};
|
||||||
|
[
|
||||||
|
uuid(B84714C0-3BFD-405D-83C5-E9C486826AD5),
|
||||||
|
helpstring("Sample SR Engine UI Class")
|
||||||
|
]
|
||||||
|
coclass SampleSREngineUI
|
||||||
|
{
|
||||||
|
[default] interface ISpTokenUI;
|
||||||
|
};
|
||||||
|
[
|
||||||
|
uuid(78771A48-CE55-46a5-B78C-B813E3403F82),
|
||||||
|
helpstring("Sample SR Engine Extension Class")
|
||||||
|
]
|
||||||
|
coclass SampleSRExtension
|
||||||
|
{
|
||||||
|
[default] interface ISampleSRExtension;
|
||||||
|
};
|
||||||
|
[
|
||||||
|
uuid(882CAE4A-99BA-490b-BF80-CF69A60454A7),
|
||||||
|
helpstring("Sample SR Engine Alternates Class")
|
||||||
|
]
|
||||||
|
coclass SampleSREngineAlternates
|
||||||
|
{
|
||||||
|
[default] interface ISpSRAlternates;
|
||||||
|
};
|
||||||
|
};
|
90
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.rc
Normal file
90
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.rc
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
//Microsoft Developer Studio generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||||
|
#include "windows.h"
|
||||||
|
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (U.S.) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||||
|
#ifdef _WIN32
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
#pragma code_page(1252)
|
||||||
|
#endif //_WIN32
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||||
|
"#include ""windows.h""\r\n"
|
||||||
|
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||||
|
"#include ""resource.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"1 TYPELIB ""sreng.tlb""\r\n"
|
||||||
|
"#include ""version.rc2""\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// REGISTRY
|
||||||
|
//
|
||||||
|
|
||||||
|
IDR_SRENG REGISTRY DISCARDABLE "sreng.rgs"
|
||||||
|
IDR_SRENGUI REGISTRY DISCARDABLE "srengui.rgs"
|
||||||
|
IDR_SRENGEXT REGISTRY DISCARDABLE "srengext.rgs"
|
||||||
|
IDR_SRENGALT REGISTRY DISCARDABLE "srengalt.rgs"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// String Table
|
||||||
|
//
|
||||||
|
|
||||||
|
STRINGTABLE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_PROJNAME "sreng"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (U.S.) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
1 TYPELIB "sreng.tlb"
|
||||||
|
#include "version.rc2"
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
101
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.rgs
Normal file
101
mp/src/utils/sapi51/Samples/CPP/Engines/SR/sreng.rgs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
HKCR
|
||||||
|
{
|
||||||
|
SampleSREngine.SampleSREngine.1 = s 'Sample SR Engine Class'
|
||||||
|
{
|
||||||
|
CLSID = s '{41B89B79-9399-11D2-9623-00C04F8EE628}'
|
||||||
|
}
|
||||||
|
SampleSREngine.SampleSREngine = s 'Sample SR Engine Class'
|
||||||
|
{
|
||||||
|
CLSID = s '{41B89B79-9399-11D2-9623-00C04F8EE628}'
|
||||||
|
CurVer = s 'SampleSREngine.SampleSREngine.1'
|
||||||
|
}
|
||||||
|
NoRemove CLSID
|
||||||
|
{
|
||||||
|
ForceRemove {41B89B79-9399-11D2-9623-00C04F8EE628} = s 'Sample SR Engine Class'
|
||||||
|
{
|
||||||
|
ProgID = s 'SampleSREngine.SampleSREngine.1'
|
||||||
|
VersionIndependentProgID = s 'SampleSREngine.SampleSREngine'
|
||||||
|
ForceRemove 'Programmable'
|
||||||
|
InprocServer32 = s '%MODULE%'
|
||||||
|
{
|
||||||
|
val ThreadingModel = s 'Both'
|
||||||
|
}
|
||||||
|
'TypeLib' = s '{41B89B6C-9399-11D2-9623-00C04F8EE628}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HKLM
|
||||||
|
{
|
||||||
|
NoRemove SOFTWARE
|
||||||
|
{
|
||||||
|
NoRemove Microsoft
|
||||||
|
{
|
||||||
|
NoRemove Speech
|
||||||
|
{
|
||||||
|
NoRemove Recognizers
|
||||||
|
{
|
||||||
|
NoRemove Tokens
|
||||||
|
{
|
||||||
|
ForceRemove SAPI5SampleEngine = s 'SAPI Developer Sample Engine'
|
||||||
|
{
|
||||||
|
val CLSID = s '{41B89B79-9399-11D2-9623-00C04F8EE628}'
|
||||||
|
val RecoExtension = s '{78771A48-CE55-46A5-B78C-B813E3403F82}'
|
||||||
|
val AlternatesCLSID = s '{882CAE4A-99BA-490B-BF80-CF69A60454A7}'
|
||||||
|
val 409 = s 'SAPI Developer Sample Engine'
|
||||||
|
|
||||||
|
ForceRemove {41B89B79-9399-11D2-9623-00C04F8EE628}
|
||||||
|
{
|
||||||
|
ForceRemove Files
|
||||||
|
{
|
||||||
|
val SampleEngDataFile = s 'C:\An_example_file_path'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ForceRemove Attributes
|
||||||
|
{
|
||||||
|
val Vendor = s 'Microsoft'
|
||||||
|
val Language = s '409;9'
|
||||||
|
val CommandAndControl = s ''
|
||||||
|
val Dictation = s ''
|
||||||
|
val Desktop = s ''
|
||||||
|
val Hypotheses = s ''
|
||||||
|
val Alternates = s 'CC;Dictation'
|
||||||
|
val DictationInCFG = s 'Anywhere;Trailing'
|
||||||
|
val WildcardInCFG = s 'Anywhere;Trailing'
|
||||||
|
val WordSequences = s ''
|
||||||
|
val SpeakingStyle = s 'Discrete;Continuous'
|
||||||
|
}
|
||||||
|
ForceRemove UI = s ''
|
||||||
|
{
|
||||||
|
ForceRemove EngineProperties = s ''
|
||||||
|
{
|
||||||
|
val CLSID = s '{B84714C0-3BFD-405D-83C5-E9C486826AD5}'
|
||||||
|
}
|
||||||
|
|
||||||
|
ForceRemove UserTraining = s ''
|
||||||
|
{
|
||||||
|
val CLSID = s '{B84714C0-3BFD-405D-83C5-E9C486826AD5}'
|
||||||
|
}
|
||||||
|
|
||||||
|
ForceRemove MicTraining = s ''
|
||||||
|
{
|
||||||
|
val CLSID = s '{B84714C0-3BFD-405D-83C5-E9C486826AD5}'
|
||||||
|
}
|
||||||
|
|
||||||
|
ForceRemove AddRemoveWord = s ''
|
||||||
|
{
|
||||||
|
val CLSID = s '{B84714C0-3BFD-405D-83C5-E9C486826AD5}'
|
||||||
|
}
|
||||||
|
|
||||||
|
ForceRemove RecoProfileProperties = s ''
|
||||||
|
{
|
||||||
|
val CLSID = s '{B84714C0-3BFD-405D-83C5-E9C486826AD5}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengalt.cpp
Normal file
137
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengalt.cpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* srengalt.h
|
||||||
|
* This file contains the implementation of the CSrEngineAlternates class.
|
||||||
|
* This implements the interface ISpSRAlternates.
|
||||||
|
* When an app calls GetAlternates or Commit on a result, SAPI will
|
||||||
|
* look for the AlternatesCLSID field in the engine object token, and
|
||||||
|
* create this object.
|
||||||
|
* It will then call the methods here, passing the relevant results information.
|
||||||
|
* This includes any serialized data the main engine has returned with
|
||||||
|
* the results to allow alternates to be generated off-line.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "srengalt.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CSrEngineAlternates::GetAlternates *
|
||||||
|
*---------------------------*
|
||||||
|
* Description:
|
||||||
|
* This method generates alternate phrases when SAPI requests them.
|
||||||
|
* The method reads the extra information returned from the SR engine
|
||||||
|
* inside the results object. This gets returned
|
||||||
|
* as alternates phrases to SAPI. In addition this method can find a private interface to engine
|
||||||
|
* from the context and query the engine for additional result information.
|
||||||
|
*
|
||||||
|
* The engine must have returned info serialised within the results object
|
||||||
|
* allowing us to produce alternatives. This is the case in the sample engine.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* FAILED(hr)
|
||||||
|
*****************************************************************************/
|
||||||
|
STDMETHODIMP CSrEngineAlternates::GetAlternates(SPPHRASEALTREQUEST *pAltRequest,
|
||||||
|
SPPHRASEALT **ppAlts, ULONG *pcAlts)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
// We will just produce one alternate
|
||||||
|
// This will replace the words in the original phrase on a one-to-one basis
|
||||||
|
// Real alternates may have different numbers of words to original,
|
||||||
|
// and replace only parts of the original.
|
||||||
|
*pcAlts = 1;
|
||||||
|
*ppAlts = (SPPHRASEALT *)::CoTaskMemAlloc(sizeof(SPPHRASEALT));
|
||||||
|
(*ppAlts)[0].ulStartElementInParent = pAltRequest->ulStartElement;
|
||||||
|
(*ppAlts)[0].cElementsInParent = pAltRequest->cElements;
|
||||||
|
(*ppAlts)[0].cElementsInAlternate = pAltRequest->cElements;
|
||||||
|
(*ppAlts)[0].pvAltExtra = NULL;
|
||||||
|
(*ppAlts)[0].cbAltExtra = 0;
|
||||||
|
|
||||||
|
// Create and fill an SPPHRASE structure
|
||||||
|
SPPHRASE phrase;
|
||||||
|
memset(&phrase, 0, sizeof(phrase));
|
||||||
|
phrase.cbSize = sizeof(phrase);
|
||||||
|
// An alternates analyzer should really query its SR engine to find it's lang id.
|
||||||
|
// For the sample engine we will just hard-code this
|
||||||
|
phrase.LangID = 1033;
|
||||||
|
|
||||||
|
WCHAR *pAlts = (WCHAR *) pAltRequest->pvResultExtra;
|
||||||
|
ULONG nAltChars = pAltRequest->cbResultExtra / sizeof(WCHAR);
|
||||||
|
ULONG nWord = 0;
|
||||||
|
|
||||||
|
// Count words in alternate data
|
||||||
|
for(ULONG i = 0; i < nAltChars; i++)
|
||||||
|
{
|
||||||
|
if(iswspace(pAlts[i]) || pAlts[i] == '\0')
|
||||||
|
{
|
||||||
|
nWord++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate elements
|
||||||
|
SPPHRASEELEMENT* pElements = (SPPHRASEELEMENT*)_alloca(sizeof(SPPHRASEELEMENT) * nWord);
|
||||||
|
memset(pElements, 0, sizeof(SPPHRASEELEMENT)*nWord);
|
||||||
|
|
||||||
|
// Add words in alternate to elements
|
||||||
|
ULONG cW = 0;
|
||||||
|
nWord = 0;
|
||||||
|
for(i = 0; i < nAltChars; i++)
|
||||||
|
{
|
||||||
|
if(iswspace(pAlts[i]) || pAlts[i] == '\0')
|
||||||
|
{
|
||||||
|
pElements[nWord].bDisplayAttributes = SPAF_ONE_TRAILING_SPACE;
|
||||||
|
WCHAR *pszWord = (WCHAR *)_alloca(sizeof(WCHAR) * (i- cW));
|
||||||
|
wcsncpy(pszWord, &pAlts[cW], i - cW);
|
||||||
|
pszWord[i - cW] = '\0';
|
||||||
|
pElements[nWord].pszDisplayText = pszWord;
|
||||||
|
|
||||||
|
cW = i + 1;
|
||||||
|
nWord++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add elements to phrase
|
||||||
|
phrase.Rule.ulCountOfElements = nWord;
|
||||||
|
phrase.pElements = pElements;
|
||||||
|
|
||||||
|
// Make phrase builder and add phrase info
|
||||||
|
CComPtr<ISpPhraseBuilder> cpBuilder;
|
||||||
|
hr = cpBuilder.CoCreateInstance(CLSID_SpPhraseBuilder);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpBuilder->InitFromPhrase(&phrase);
|
||||||
|
}
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
(*ppAlts)[0].pPhrase = cpBuilder;
|
||||||
|
(*ppAlts)[0].pPhrase->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alternates class can also query enginethrough private interface
|
||||||
|
CComPtr<ISampleSRExtension> m_cpExt;
|
||||||
|
hr = pAltRequest->pRecoContext->QueryInterface(&m_cpExt);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = m_cpExt->ExamplePrivateEngineCall();
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CSrEngineAlternates::Commit *
|
||||||
|
*---------------------------*
|
||||||
|
* Description:
|
||||||
|
* Here the engine could use the information from the application
|
||||||
|
* about which was the correct alternate in order to do supervised
|
||||||
|
* adaptation.
|
||||||
|
* In this sample we do nothing here.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
*****************************************************************************/
|
||||||
|
STDMETHODIMP CSrEngineAlternates::Commit(SPPHRASEALTREQUEST *pAltRequest,
|
||||||
|
SPPHRASEALT *pAlt, void **ppvResultExtra, ULONG *pcbResultExtra)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
48
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengalt.h
Normal file
48
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengalt.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* srengalt.h
|
||||||
|
* This file contains the declaration of the CSrEngineAlternates class.
|
||||||
|
* This implements the interface ISpSRAlternates.
|
||||||
|
* When an app calls GetAlternates or Commit on a result, SAPI will
|
||||||
|
* look for the AlternatesCLSID field in the engine object token, and
|
||||||
|
* create this object.
|
||||||
|
* It will then call the methods here, passing the relevant results information.
|
||||||
|
* This includes any serialized data the main engine has returned with
|
||||||
|
* the results to allow alternates to be generated off-line.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "sreng.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
class ATL_NO_VTABLE CSrEngineAlternates :
|
||||||
|
public CComObjectRootEx<CComMultiThreadModel>,
|
||||||
|
public CComCoClass<CSrEngineAlternates, &CLSID_SampleSREngineAlternates>,
|
||||||
|
public ISpSRAlternates
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DECLARE_REGISTRY_RESOURCEID(IDR_SRENGALT)
|
||||||
|
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CSrEngineAlternates)
|
||||||
|
COM_INTERFACE_ENTRY(ISpSRAlternates)
|
||||||
|
END_COM_MAP()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
STDMETHODIMP GetAlternates(
|
||||||
|
SPPHRASEALTREQUEST *pAltRequest,
|
||||||
|
SPPHRASEALT **ppAlts,
|
||||||
|
ULONG *pcAlts);
|
||||||
|
|
||||||
|
STDMETHODIMP Commit(
|
||||||
|
SPPHRASEALTREQUEST *pAltRequest,
|
||||||
|
SPPHRASEALT *pAlt,
|
||||||
|
void **ppvResultExtra,
|
||||||
|
ULONG *pcbResultExtra);
|
||||||
|
};
|
26
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengalt.rgs
Normal file
26
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengalt.rgs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
HKCR
|
||||||
|
{
|
||||||
|
SampleSREngineAlternates.SampleSREngineAlternates.1 = s 'Sample SR Engine Alternates Class'
|
||||||
|
{
|
||||||
|
CLSID = s '{882CAE4A-99BA-490b-BF80-CF69A60454A7}'
|
||||||
|
}
|
||||||
|
SampleSREngineAlternates.SampleSREngineAlternates = s 'Sample SR Engine Alternates Class'
|
||||||
|
{
|
||||||
|
CLSID = s '{882CAE4A-99BA-490B-BF80-CF69A60454A7}'
|
||||||
|
CurVer = s 'SampleSREngineAlternates.SampleSREngineAlternates.1'
|
||||||
|
}
|
||||||
|
NoRemove CLSID
|
||||||
|
{
|
||||||
|
ForceRemove {882CAE4A-99BA-490B-BF80-CF69A60454A7} = s 'SampleSrEngineAlternates Class'
|
||||||
|
{
|
||||||
|
ProgID = s 'SampleSREngineAlternates.SampleSREngineAlternates.1'
|
||||||
|
VersionIndependentProgID = s 'SampleSREngineAlternates.SampleSREngineAlternates'
|
||||||
|
ForceRemove 'Programmable'
|
||||||
|
InprocServer32 = s '%MODULE%'
|
||||||
|
{
|
||||||
|
val ThreadingModel = s 'Both'
|
||||||
|
}
|
||||||
|
'TypeLib' = s '{41B89B6C-9399-11D2-9623-00C04F8EE628}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengext.cpp
Normal file
31
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengext.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* srengext.cpp
|
||||||
|
* This file contains the implementation of the CSampleSRExtension class.
|
||||||
|
* This implements the custom interface ISampleSRExtension.
|
||||||
|
* When an app QI's for this from the reco context, SAPI will
|
||||||
|
* look for the ExtensionCLSID field in the engine object token, and
|
||||||
|
* create this object and then QI for the requested interface.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "srengext.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CSampleSRExtension::ExamplePrivateEngineCall *
|
||||||
|
*----------------------------------------------*
|
||||||
|
* Description:
|
||||||
|
* This method shows an example of calling back to the main engine object.
|
||||||
|
* When CallEngine is called, the data supplied will get passed by SAPI
|
||||||
|
* to the ISpSREngine::PrivateCall method in CSrEngine.
|
||||||
|
* Return:
|
||||||
|
* S_OK
|
||||||
|
* FAILED(hr)
|
||||||
|
*****************************************************************************/
|
||||||
|
STDMETHODIMP CSampleSRExtension::ExamplePrivateEngineCall(void)
|
||||||
|
{
|
||||||
|
// We can use this method to pass data to and from the actual engine class, via the context
|
||||||
|
static BYTE Data[4] = { 1, 2, 3, 4 };
|
||||||
|
return m_pEngineCall->CallEngine( (void*)Data, sp_countof(Data) );
|
||||||
|
}
|
56
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengext.h
Normal file
56
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengext.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* srengext.h
|
||||||
|
* This file contains the declaration of the CSampleSRExtension class.
|
||||||
|
* This implements the custom interface ISampleSRExtension.
|
||||||
|
* When an app QI's for this from the reco context, SAPI will
|
||||||
|
* look for the ExtensionCLSID field in the engine object token, and
|
||||||
|
* create this object and then QI for the requested interface.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "sreng.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
class ATL_NO_VTABLE CSampleSRExtension :
|
||||||
|
public CComObjectRootEx<CComMultiThreadModel>,
|
||||||
|
public CComCoClass<CSampleSRExtension, &CLSID_SampleSRExtension>,
|
||||||
|
public ISampleSRExtension
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DECLARE_REGISTRY_RESOURCEID(IDR_SRENGEXT)
|
||||||
|
DECLARE_GET_CONTROLLING_UNKNOWN()
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CSampleSRExtension)
|
||||||
|
COM_INTERFACE_ENTRY(ISampleSRExtension)
|
||||||
|
END_COM_MAP()
|
||||||
|
|
||||||
|
HRESULT FinalConstruct()
|
||||||
|
{
|
||||||
|
// We can query back to SAPI to find both the reco context, and,
|
||||||
|
// an IID__ISpPrivateEngineCall interface which can be used to call
|
||||||
|
// back to the main engine object.
|
||||||
|
HRESULT hr;
|
||||||
|
hr = OuterQueryInterface(IID__ISpPrivateEngineCall, (void **)&m_pEngineCall);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = OuterQueryInterface(IID_ISpRecoContext, (void **)&m_pRecoCtxt);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
GetControllingUnknown()->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP ExamplePrivateEngineCall(void); // Just a test method
|
||||||
|
|
||||||
|
private:
|
||||||
|
_ISpPrivateEngineCall *m_pEngineCall;
|
||||||
|
ISpRecoContext *m_pRecoCtxt;
|
||||||
|
};
|
26
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengext.rgs
Normal file
26
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengext.rgs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
HKCR
|
||||||
|
{
|
||||||
|
SampleSrEngineExt.SampleSrEngineExt.1 = s 'Sample SR Engine Extension Class'
|
||||||
|
{
|
||||||
|
CLSID = s '{78771A48-CE55-46A5-B78C-B813E3403F82}'
|
||||||
|
}
|
||||||
|
SampleSrEngineExt.SampleSrEngineExt = s 'Sample SR Engine Extension Class'
|
||||||
|
{
|
||||||
|
CLSID = s '{78771A48-CE55-46A5-B78C-B813E3403F82}'
|
||||||
|
CurVer = s 'SampleSrEngineExt.SampleSrEngineExt.1'
|
||||||
|
}
|
||||||
|
NoRemove CLSID
|
||||||
|
{
|
||||||
|
ForceRemove {78771A48-CE55-46A5-B78C-B813E3403F82} = s 'SampleSrEngineExt Class'
|
||||||
|
{
|
||||||
|
ProgID = s 'SampleSrEngineExt.SampleSrEngineExt.1'
|
||||||
|
VersionIndependentProgID = s 'SampleSrEngineExt.SampleSrEngineExt'
|
||||||
|
ForceRemove 'Programmable'
|
||||||
|
InprocServer32 = s '%MODULE%'
|
||||||
|
{
|
||||||
|
val ThreadingModel = s 'Both'
|
||||||
|
}
|
||||||
|
'TypeLib' = s '{41B89B6C-9399-11D2-9623-00C04F8EE628}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1944
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengobj.cpp
Normal file
1944
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengobj.cpp
Normal file
File diff suppressed because it is too large
Load Diff
347
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengobj.h
Normal file
347
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengobj.h
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* srengobj.h
|
||||||
|
* This file contains the declaration of the CSrEngine class.
|
||||||
|
* This implements ISpSREngine and ISpObjectWithToken.
|
||||||
|
* This is the main recognition object
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "sreng.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
// A list of reco contexts is stored. Each entry in the list is an instance of this class.
|
||||||
|
class CContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CContext * m_pNext;
|
||||||
|
BOOL operator==(SPRECOCONTEXTHANDLE hContext)
|
||||||
|
{
|
||||||
|
return (m_hSapiContext == hContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
CContext(SPRECOCONTEXTHANDLE hSapiContext) :
|
||||||
|
m_hSapiContext(hSapiContext)
|
||||||
|
{}
|
||||||
|
|
||||||
|
SPRECOCONTEXTHANDLE m_hSapiContext; // The reco context handle given by SAPI
|
||||||
|
};
|
||||||
|
|
||||||
|
// A list of reco grammars is stored. Each entry in the list is an instance of this class.
|
||||||
|
class CDrvGrammar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CDrvGrammar * m_pNext;
|
||||||
|
SPGRAMMARHANDLE m_hSapiGrammar; // The grammar handle given by SAPI
|
||||||
|
BOOL m_SLMLoaded; // Does the grammar have an associated SLM for dictation
|
||||||
|
BOOL m_SLMActive; // Is the dictation active
|
||||||
|
WCHAR* m_pWordSequenceText; // The text of the word sequence buffer if one is set
|
||||||
|
ULONG m_cchText; // The size of the word sequence buffer
|
||||||
|
SPTEXTSELECTIONINFO* m_pInfo; // The text selection of the word sequence buffer
|
||||||
|
|
||||||
|
CDrvGrammar(SPGRAMMARHANDLE hSapiGrammar) :
|
||||||
|
m_hSapiGrammar(hSapiGrammar),
|
||||||
|
m_SLMLoaded(FALSE),
|
||||||
|
m_SLMActive(FALSE),
|
||||||
|
m_pWordSequenceText(NULL),
|
||||||
|
m_cchText(0),
|
||||||
|
m_pInfo(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~CDrvGrammar()
|
||||||
|
{
|
||||||
|
// Free up resources
|
||||||
|
//For each grammar object going to be released, SAPI would call SetWordSequenceData(NULL, 0, NULL).
|
||||||
|
//SetWordSequenceData and SetTextSelection would release the memories.
|
||||||
|
//There is no need to release memories referred by m_pWordSequenceText and m_pInfo here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
CDrvGrammar()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG Compare(const CDrvGrammar *, const CDrvGrammar *)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// The RecognizeStream thread read audio data in blocks. For each block
|
||||||
|
// it decides if the data is speech or silence and adds that value to this queue.
|
||||||
|
// The decoder thread reads these and processes them.
|
||||||
|
// A critical section is used to make the queue thread-safe, and an event is used to
|
||||||
|
// show if the buffer has space or not.
|
||||||
|
// This very roughtly simulates the idea of doing features extraction on
|
||||||
|
// one thread and passes the feature stream to the decoder.
|
||||||
|
class CFrameQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BOOL m_aFrames[100]; // The queue of speech/silence values
|
||||||
|
ULONG m_cFrames;
|
||||||
|
ULONG m_ulHeadIndex;
|
||||||
|
HANDLE m_hSpaceAvailEvent;
|
||||||
|
CRITICAL_SECTION m_cs;
|
||||||
|
|
||||||
|
CFrameQueue()
|
||||||
|
{
|
||||||
|
m_cFrames = 0;
|
||||||
|
m_ulHeadIndex = 0;
|
||||||
|
m_hSpaceAvailEvent = NULL;
|
||||||
|
InitializeCriticalSection(&m_cs);
|
||||||
|
}
|
||||||
|
~CFrameQueue()
|
||||||
|
{
|
||||||
|
DeleteCriticalSection(&m_cs);
|
||||||
|
}
|
||||||
|
void SetSpaceAvailEvent(HANDLE h)
|
||||||
|
{
|
||||||
|
m_hSpaceAvailEvent = h;
|
||||||
|
}
|
||||||
|
void InsertTail(BOOL b)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&m_cs);
|
||||||
|
ULONG ulTailIndex = (m_ulHeadIndex + m_cFrames) % sp_countof(m_aFrames);
|
||||||
|
m_aFrames[ulTailIndex] = b;
|
||||||
|
m_cFrames++;
|
||||||
|
if (m_cFrames == sp_countof(m_aFrames))
|
||||||
|
{
|
||||||
|
ResetEvent(m_hSpaceAvailEvent);
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&m_cs);
|
||||||
|
}
|
||||||
|
BOOL IsFull()
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&m_cs);
|
||||||
|
BOOL b = (m_cFrames == sp_countof(m_aFrames));
|
||||||
|
LeaveCriticalSection(&m_cs);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
BOOL RemoveHead()
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&m_cs);
|
||||||
|
BOOL b = m_aFrames[m_ulHeadIndex];
|
||||||
|
m_ulHeadIndex = (m_ulHeadIndex + 1) % sp_countof(m_aFrames);
|
||||||
|
m_cFrames--;
|
||||||
|
SetEvent(m_hSpaceAvailEvent);
|
||||||
|
LeaveCriticalSection(&m_cs);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
BOOL HasData()
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&m_cs);
|
||||||
|
ULONG cFrames = m_cFrames;
|
||||||
|
LeaveCriticalSection(&m_cs);
|
||||||
|
return cFrames;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Class so we can use CSpBasicQueue to store rule information
|
||||||
|
class CRuleEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BOOL operator==(SPRULEHANDLE rh)
|
||||||
|
{
|
||||||
|
return (m_hRule == rh);
|
||||||
|
}
|
||||||
|
CRuleEntry * m_pNext;
|
||||||
|
SPRULEHANDLE m_hRule; // SAPI rule handle
|
||||||
|
BOOL m_fTopLevel; // Shows if rule can be activated
|
||||||
|
BOOL m_fActive; // Shows if rule is currectly active
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The main CSrEngine class
|
||||||
|
|
||||||
|
class ATL_NO_VTABLE CSrEngine :
|
||||||
|
public CComObjectRootEx<CComMultiThreadModel>,
|
||||||
|
public CComCoClass<CSrEngine, &CLSID_SampleSREngine>,
|
||||||
|
public ISpSREngine,
|
||||||
|
public ISpObjectWithToken,
|
||||||
|
public ISpThreadTask
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSrEngine() :
|
||||||
|
m_ulNextGrammarIndex(0),
|
||||||
|
m_cActive(0),
|
||||||
|
m_bPhraseStarted(FALSE),
|
||||||
|
m_bSoundStarted(FALSE),
|
||||||
|
m_hQueueHasRoom(NULL),
|
||||||
|
m_hRequestSync(NULL),
|
||||||
|
m_LangID(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
DECLARE_REGISTRY_RESOURCEID(IDR_SRENG)
|
||||||
|
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CSrEngine)
|
||||||
|
COM_INTERFACE_ENTRY(ISpSREngine)
|
||||||
|
COM_INTERFACE_ENTRY(ISpObjectWithToken)
|
||||||
|
END_COM_MAP()
|
||||||
|
|
||||||
|
private:
|
||||||
|
HANDLE m_hRequestSync;
|
||||||
|
CFrameQueue m_FrameQueue;
|
||||||
|
ULONG m_cBlahBlah;
|
||||||
|
CSpBasicQueue<CDrvGrammar> m_GrammarList;
|
||||||
|
CSpBasicQueue<CContext> m_ContextList;
|
||||||
|
ULONG m_ulNextGrammarIndex;
|
||||||
|
ULONG m_cActive;
|
||||||
|
ULONGLONG m_ullStart;
|
||||||
|
ULONGLONG m_ullEnd;
|
||||||
|
BOOL m_bSoundStarted:1;
|
||||||
|
BOOL m_bPhraseStarted:1;
|
||||||
|
CComPtr<ISpSREngineSite> m_cpSite;
|
||||||
|
CComPtr<ISpThreadControl> m_cpDecoderThread;
|
||||||
|
HANDLE m_hQueueHasRoom;
|
||||||
|
CSpBasicQueue<CRuleEntry> m_RuleList;
|
||||||
|
CComPtr<ISpLexicon> m_cpLexicon;
|
||||||
|
CComPtr<ISpObjectToken> m_cpEngineObjectToken;
|
||||||
|
CComPtr<ISpObjectToken> m_cpUserObjectToken;
|
||||||
|
LANGID m_LangID;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
HRESULT RandomlyWalkRule(SPRECORESULTINFO * pResult, ULONG nWords, ULONGLONG ullAudioPos, ULONG ulAudioSize);
|
||||||
|
HRESULT RecurseWalk(SPSTATEHANDLE hState, SPPATHENTRY * pPath, ULONG * pcTrans);
|
||||||
|
HRESULT WalkCFGRule(SPRECORESULTINFO * pResult, ULONG cRulesActive, BOOL fHypothesis,
|
||||||
|
ULONG nWords, ULONGLONG ullAudioPos, ULONG ulAudioSize);
|
||||||
|
HRESULT WalkSLM(SPRECORESULTINFO * pResult, ULONG cSLMActive,
|
||||||
|
ULONG nWords, ULONGLONG ullAudioPos, ULONG ulAudioSize);
|
||||||
|
HRESULT WalkTextBuffer(void* pvGrammarCookie, SPPATHENTRY * pPath, SPTRANSITIONID hId, ULONG * pcTrans);
|
||||||
|
|
||||||
|
HRESULT AddEvent(SPEVENTENUM eEvent, ULONGLONG ullStreamPos, WPARAM wParam = 0, LPARAM lParam = 0);
|
||||||
|
HRESULT AddEventString(SPEVENTENUM eEvent, ULONGLONG ulLStreamPos, const WCHAR * psz, WPARAM = 0);
|
||||||
|
|
||||||
|
HRESULT CreatePhraseFromRule( CRuleEntry * pRule, BOOL fHypothesis,
|
||||||
|
ULONGLONG ullAudioPos, ULONG ulAudioSize,
|
||||||
|
ISpPhraseBuilder** ppPhrase );
|
||||||
|
|
||||||
|
CRuleEntry* FindRule( ULONG ulRuleIndex );
|
||||||
|
CRuleEntry* NextRuleAlt( CRuleEntry * pPriRule, CRuleEntry * pLastRule );
|
||||||
|
|
||||||
|
void _CheckRecognition();
|
||||||
|
void _NotifyRecognition(BOOL fHypothesis, ULONG nWords);
|
||||||
|
|
||||||
|
// ATL contstructor / destructor
|
||||||
|
HRESULT FinalConstruct();
|
||||||
|
HRESULT FinalRelease();
|
||||||
|
|
||||||
|
// Initialization methods
|
||||||
|
STDMETHODIMP SetObjectToken(ISpObjectToken * pToken);
|
||||||
|
STDMETHODIMP GetObjectToken(ISpObjectToken ** ppToken);
|
||||||
|
|
||||||
|
STDMETHODIMP SetRecoProfile(ISpObjectToken * pProfileToken);
|
||||||
|
STDMETHODIMP SetSite(ISpSREngineSite *pSite);
|
||||||
|
STDMETHODIMP GetInputAudioFormat(const GUID * pSrcFormatId, const WAVEFORMATEX * pSrcWFEX,
|
||||||
|
GUID * pDesiredFormatId, WAVEFORMATEX ** ppCoMemDesiredWFEX);
|
||||||
|
|
||||||
|
STDMETHODIMP OnCreateRecoContext(SPRECOCONTEXTHANDLE hSAPIRecoContext, void ** ppvDrvCtxt);
|
||||||
|
STDMETHODIMP OnDeleteRecoContext(void * pvDrvCtxt);
|
||||||
|
|
||||||
|
STDMETHODIMP OnCreateGrammar(void * pvEngineRecoContext,
|
||||||
|
SPGRAMMARHANDLE hSAPIGrammar,
|
||||||
|
void ** ppvEngineGrammar);
|
||||||
|
|
||||||
|
STDMETHODIMP OnDeleteGrammar(void * pvEngineGrammar);
|
||||||
|
|
||||||
|
// CFG methods
|
||||||
|
STDMETHODIMP WordNotify(SPCFGNOTIFY Action, ULONG cWords, const SPWORDENTRY * pWords);
|
||||||
|
STDMETHODIMP RuleNotify(SPCFGNOTIFY Action, ULONG cRules, const SPRULEENTRY * pRules);
|
||||||
|
|
||||||
|
// Proprietary grammar methods
|
||||||
|
// - used to implement an engine-specific grammar format
|
||||||
|
// - this sample does not implement these
|
||||||
|
STDMETHODIMP LoadProprietaryGrammar(void * pvEngineGrammar,
|
||||||
|
REFGUID rguidParam,
|
||||||
|
const WCHAR * pszStringParam,
|
||||||
|
const void * pvDataParam,
|
||||||
|
ULONG ulDataSize,
|
||||||
|
SPLOADOPTIONS Options)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP UnloadProprietaryGrammar(void * pvEngineGrammar)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP SetProprietaryRuleState(void * pvEngineGrammar,
|
||||||
|
const WCHAR * pszName,
|
||||||
|
void * pvReserved,
|
||||||
|
SPRULESTATE NewState,
|
||||||
|
ULONG * pcRulesChanged)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
STDMETHODIMP SetProprietaryRuleIdState(void * pvEngineGrammar,
|
||||||
|
DWORD dwRuleId,
|
||||||
|
SPRULESTATE NewState)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since this engine does not support proprietary grammars, we do not need to implement
|
||||||
|
// this method other than just returning S_OK. Note to implementors: Do NOT return
|
||||||
|
// E_NOTIMPL. Just return S_OK and ignore this data if you do not need it to implement
|
||||||
|
// proprietary grammars.
|
||||||
|
STDMETHODIMP SetGrammarState(void * pvEngineGrammar, SPGRAMMARSTATE eGrammarState)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
STDMETHODIMP SetContextState(void * pvEngineContxt, SPCONTEXTSTATE eCtxtState)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Dictation methods
|
||||||
|
STDMETHODIMP LoadSLM(void * pvEngineGrammar, const WCHAR * pszTopicName);
|
||||||
|
STDMETHODIMP UnloadSLM(void * pvEngineGrammar);
|
||||||
|
STDMETHODIMP SetSLMState(void * pvEngineGrammar, SPRULESTATE NewState);
|
||||||
|
|
||||||
|
STDMETHODIMP IsPronounceable(void *pDrvGrammar, const WCHAR *pszWord, SPWORDPRONOUNCEABLE * pWordPronounceable);
|
||||||
|
STDMETHODIMP SetWordSequenceData(void * pvEngineGrammar, const WCHAR * pText, ULONG cchText, const SPTEXTSELECTIONINFO * pInfo);
|
||||||
|
STDMETHODIMP SetTextSelection(void * pvEngineGrammar, const SPTEXTSELECTIONINFO * pInfo);
|
||||||
|
STDMETHODIMP SetAdaptationData(void * pvEngineCtxtCookie, const WCHAR * pText, const ULONG cch);
|
||||||
|
|
||||||
|
// Property methods
|
||||||
|
STDMETHODIMP SetPropertyNum( SPPROPSRC eSrc, void* pvSrcObj, const WCHAR* pName, LONG lValue );
|
||||||
|
STDMETHODIMP GetPropertyNum( SPPROPSRC eSrc, void* pvSrcObj, const WCHAR* pName, LONG * plValue );
|
||||||
|
STDMETHODIMP SetPropertyString( SPPROPSRC eSrc, void* pvSrcObj, const WCHAR* pName, const WCHAR* pValue );
|
||||||
|
STDMETHODIMP GetPropertyString( SPPROPSRC eSrc, void* pvSrcObj, const WCHAR* pName, WCHAR** ppCoMemValue );
|
||||||
|
|
||||||
|
|
||||||
|
// The main recognition method
|
||||||
|
STDMETHODIMP RecognizeStream(REFGUID rguidFmtId, const WAVEFORMATEX * pWaveFormatEx,
|
||||||
|
HANDLE hRequestSync, HANDLE hDataAvailable,
|
||||||
|
HANDLE hExit, BOOL fNewAudioStream, BOOL fRealTimeAudio,
|
||||||
|
ISpObjectToken * pAudioObjectToken);
|
||||||
|
|
||||||
|
STDMETHODIMP PrivateCall(void * pvEngineContext, void * pCallFrame, ULONG ulCallFrameSize);
|
||||||
|
STDMETHODIMP PrivateCallEx(void * pvEngineContext, const void * pInCallFrame, ULONG ulCallFrameSize,
|
||||||
|
void ** ppvCoMemResponse, ULONG * pcbResponse);
|
||||||
|
|
||||||
|
|
||||||
|
// ISpThreadTask methods
|
||||||
|
STDMETHODIMP InitThread( void * pvTaskData, HWND hwnd )
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
LRESULT STDMETHODCALLTYPE WindowMessage( void *pvTaskData, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam )
|
||||||
|
{
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP ThreadProc( void *pvTaskData, HANDLE hExitThreadEvent, HANDLE hNotifyEvent, HWND hwndWorker, volatile const BOOL * pfContinueProcessing );
|
||||||
|
};
|
||||||
|
|
79
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengui.cpp
Normal file
79
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengui.cpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* srengui.cpp
|
||||||
|
* This file contains the implementation of the CSrEngineUI class.
|
||||||
|
* This implements ISpTokenUI. This is used by the app to display UI.
|
||||||
|
* The methods here can either be called by the app directly from ISpObjectToken,
|
||||||
|
* or they can be called from the reco instance, in which case the methods
|
||||||
|
* are able to make a private call back to the main engine object.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "sreng.h"
|
||||||
|
#include "srengui.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CSrEngineUI::IsUISupported *
|
||||||
|
*----------------------------*
|
||||||
|
* Description:
|
||||||
|
* Determine if the UI is supported. A reference to the main SR engine
|
||||||
|
* object (if it has been created), can be obtained from punkObject.
|
||||||
|
* If none-NULL this may be an ISpRecoContext, from which an engine
|
||||||
|
* extension interface can be obtained.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* S_OK on success
|
||||||
|
* E_INVALIDARG on invalid arguments
|
||||||
|
*****************************************************************************/
|
||||||
|
STDMETHODIMP CSrEngineUI::IsUISupported(const WCHAR * pszTypeOfUI, void * pvExtraData, ULONG cbExtraData, IUnknown * punkObject, BOOL *pfSupported)
|
||||||
|
{
|
||||||
|
*pfSupported = FALSE;
|
||||||
|
|
||||||
|
// We can do both engine specific properties as well as default settings (defaults when punkObject == NULL)
|
||||||
|
if (wcscmp(pszTypeOfUI, SPDUI_EngineProperties) == 0)
|
||||||
|
*pfSupported = TRUE;
|
||||||
|
|
||||||
|
// We can only do user training if we get passed an engine
|
||||||
|
if (wcscmp(pszTypeOfUI, SPDUI_UserTraining) == 0 && punkObject != NULL)
|
||||||
|
*pfSupported = TRUE;
|
||||||
|
|
||||||
|
// We can only do mic training if we get passed an engine
|
||||||
|
if (wcscmp(pszTypeOfUI, SPDUI_MicTraining) == 0 && punkObject != NULL)
|
||||||
|
*pfSupported = TRUE;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CSrEngineUI::DisplayUI *
|
||||||
|
*------------------------*
|
||||||
|
* Description:
|
||||||
|
* Display the UI requested
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* S_OK on success
|
||||||
|
*****************************************************************************/
|
||||||
|
STDMETHODIMP CSrEngineUI::DisplayUI(HWND hwndParent, const WCHAR * pszTitle, const WCHAR * pszTypeOfUI, void * pvExtraData, ULONG cbExtraData, ISpObjectToken * pToken, IUnknown * punkObject)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (wcscmp(pszTypeOfUI, SPDUI_EngineProperties) == 0)
|
||||||
|
{
|
||||||
|
if (punkObject)
|
||||||
|
{
|
||||||
|
MessageBoxW(hwndParent, L"Developer Sample Engine: Replace this with real engine properties dialog.", pszTitle, MB_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcscmp(pszTypeOfUI, SPDUI_UserTraining) == 0)
|
||||||
|
{
|
||||||
|
MessageBoxW(hwndParent, L"Developer Sample Engine: Replace this with real user training wizard / dialog.", pszTitle, MB_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcscmp(pszTypeOfUI, SPDUI_MicTraining) == 0)
|
||||||
|
{
|
||||||
|
MessageBoxW(hwndParent, L"Developer Sample Engine: Replace this with real microphone training wizard / dialog.", pszTitle, MB_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
47
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengui.h
Normal file
47
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengui.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* srengui.cpp
|
||||||
|
* This file contains the declaration of the CSrEngineUI class.
|
||||||
|
* This implements ISpTokenUI. This is used by the app to display UI.
|
||||||
|
* The methods here can either be called by the app directly from ISpObjectToken,
|
||||||
|
* or they can be called from the reco instance, in which case the methods
|
||||||
|
* are able to make a private call back to the main engine object.
|
||||||
|
*
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
class ATL_NO_VTABLE CSrEngineUI :
|
||||||
|
public CComObjectRootEx<CComMultiThreadModel>,
|
||||||
|
public CComCoClass<CSrEngineUI, &CLSID_SampleSREngineUI>,
|
||||||
|
public ISpTokenUI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DECLARE_REGISTRY_RESOURCEID(IDR_SRENGUI)
|
||||||
|
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CSrEngineUI)
|
||||||
|
COM_INTERFACE_ENTRY(ISpTokenUI)
|
||||||
|
END_COM_MAP()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
STDMETHODIMP IsUISupported(
|
||||||
|
const WCHAR * pszTypeOfUI,
|
||||||
|
void * pvExtraData,
|
||||||
|
ULONG cbExtraData,
|
||||||
|
IUnknown * punkObject,
|
||||||
|
BOOL *pfSupported);
|
||||||
|
STDMETHODIMP DisplayUI(
|
||||||
|
HWND hwndParent,
|
||||||
|
const WCHAR * pszTitle,
|
||||||
|
const WCHAR * pszTypeOfUI,
|
||||||
|
void * pvExtraData,
|
||||||
|
ULONG cbExtraData,
|
||||||
|
ISpObjectToken * pToken,
|
||||||
|
IUnknown * punkObject);
|
||||||
|
};
|
26
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengui.rgs
Normal file
26
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengui.rgs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
HKCR
|
||||||
|
{
|
||||||
|
SampleSrEngineUI.SampleSrEngineUI.1 = s 'Sample SR Engine Class'
|
||||||
|
{
|
||||||
|
CLSID = s '{B84714C0-3BFD-405D-83C5-E9C486826AD5}'
|
||||||
|
}
|
||||||
|
SampleSrEngineUI.SampleSrEngineUI = s 'Sample SR Engine Class'
|
||||||
|
{
|
||||||
|
CLSID = s '{B84714C0-3BFD-405D-83C5-E9C486826AD5}'
|
||||||
|
CurVer = s 'SampleSrEngineUI.SampleSrEngineUI.1'
|
||||||
|
}
|
||||||
|
NoRemove CLSID
|
||||||
|
{
|
||||||
|
ForceRemove {B84714C0-3BFD-405D-83C5-E9C486826AD5} = s 'SampleSrEngineUI Class'
|
||||||
|
{
|
||||||
|
ProgID = s 'SampleSrEngineUI.SampleSrEngineUI.1'
|
||||||
|
VersionIndependentProgID = s 'SampleSrEngineUI.SampleSrEngineUI'
|
||||||
|
ForceRemove 'Programmable'
|
||||||
|
InprocServer32 = s '%MODULE%'
|
||||||
|
{
|
||||||
|
val ThreadingModel = s 'Both'
|
||||||
|
}
|
||||||
|
'TypeLib' = s '{41B89B6C-9399-11D2-9623-00C04F8EE628}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengver.h
Normal file
78
mp/src/utils/sapi51/Samples/CPP/Engines/SR/srengver.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* *
|
||||||
|
* VERSION.H -- Version information for internal builds *
|
||||||
|
* *
|
||||||
|
* This file is only modified by the official builder to update the *
|
||||||
|
* VERSION, VER_PRODUCTVERSION and VER_PRODUCTVERSION_STR values *
|
||||||
|
* *
|
||||||
|
* version.h is created on the fly from verhead.bat and vertail.h, *
|
||||||
|
* with the current version numbers inserted in between *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef VER_H
|
||||||
|
/* ver.h defines constants needed by the VS_VERSION_INFO structure */
|
||||||
|
//#include <winver.h>
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
#define VER_FILETYPE VFT_APP
|
||||||
|
#define VER_FILESUBTYPE VFT2_UNKNOWN
|
||||||
|
#define VER_FILEDESCRIPTION_STR "SR SAMPLE ENGINE 5"
|
||||||
|
#define VER_INTERNALNAME_STR "SRSAMPLEENG5"
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* the following entry should be phased out in favor of */
|
||||||
|
/* VER_PRODUCTVERSION_STR, but is used in the shell today. */
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* the following values should be modified by the official */
|
||||||
|
/* builder for each build */
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define VERSION "5.0"
|
||||||
|
#define VER_FILEVERSION_STR "5.0"
|
||||||
|
#define VER_FILEVERSION 5,0
|
||||||
|
#define VER_PRODUCTVERSION_STR "5.0"
|
||||||
|
#define VER_PRODUCTVERSION 5,0
|
||||||
|
|
||||||
|
#define OFFICIAL 1
|
||||||
|
#define FINAL 1
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* the following section defines values used in the version */
|
||||||
|
/* data structure for all files, and which do not change. */
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* default is nodebug */
|
||||||
|
#if _DEBUG
|
||||||
|
#define VER_DEBUG VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
#define VER_DEBUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* default is privatebuild */
|
||||||
|
#ifndef OFFICIAL
|
||||||
|
#define VER_PRIVATEBUILD VS_FF_PRIVATEBUILD
|
||||||
|
#else
|
||||||
|
#define VER_PRIVATEBUILD 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* default is prerelease */
|
||||||
|
#ifndef FINAL
|
||||||
|
#define VER_PRERELEASE VS_FF_PRERELEASE
|
||||||
|
#else
|
||||||
|
#define VER_PRERELEASE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
#define VER_FILEOS VOS_DOS_WINDOWS32
|
||||||
|
#define VER_FILEFLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG)
|
||||||
|
|
||||||
|
#define VER_COMPANYNAME_STR "Microsoft Corporation\0"
|
||||||
|
#define VER_PRODUCTNAME_STR "Microsoft\256 Windows(TM) Operating System\0"
|
||||||
|
#define VER_LEGALTRADEMARKS_STR \
|
||||||
|
"Microsoft\256 is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
|
||||||
|
|
||||||
|
//#include "\sapi5\build\common.ver"
|
13
mp/src/utils/sapi51/Samples/CPP/Engines/SR/stdafx.cpp
Normal file
13
mp/src/utils/sapi51/Samples/CPP/Engines/SR/stdafx.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// stdafx.cpp : source file that includes just the standard includes
|
||||||
|
// stdafx.pch will be the pre-compiled header
|
||||||
|
// stdafx.obj will contain the pre-compiled type information
|
||||||
|
//Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#ifdef _ATL_STATIC_REGISTRY
|
||||||
|
#include <statreg.h>
|
||||||
|
#include <statreg.cpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <atlimpl.cpp>
|
38
mp/src/utils/sapi51/Samples/CPP/Engines/SR/stdafx.h
Normal file
38
mp/src/utils/sapi51/Samples/CPP/Engines/SR/stdafx.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// stdafx.h : include file for standard system include files,
|
||||||
|
// or project specific include files that are used frequently,
|
||||||
|
// but are changed infrequently
|
||||||
|
|
||||||
|
#if !defined(AFX_STDAFX_H__41B89B6F_9399_11D2_9623_00C04F8EE628__INCLUDED_)
|
||||||
|
#define AFX_STDAFX_H__41B89B6F_9399_11D2_9623_00C04F8EE628__INCLUDED_
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif // _MSC_VER > 1000
|
||||||
|
|
||||||
|
#ifndef STRICT
|
||||||
|
#define STRICT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0400
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <atlbase.h>
|
||||||
|
//You may derive a class from CComModule and use it if you want to override
|
||||||
|
//something, but do not change the name of _Module
|
||||||
|
|
||||||
|
extern CComModule _Module;
|
||||||
|
#include <atlcom.h>
|
||||||
|
|
||||||
|
#include <spddkhlp.h>
|
||||||
|
|
||||||
|
// Platform SDK needs to be installed for this sample because it #includes shfolder.h
|
||||||
|
#ifndef MAXULONG_PTR
|
||||||
|
#error This sample application requires a newer version of the Platform SDK than you have installed.
|
||||||
|
#endif // MAXULONG_PTR
|
||||||
|
|
||||||
|
|
||||||
|
//{{AFX_INSERT_LOCATION}}
|
||||||
|
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||||
|
|
||||||
|
#endif // !defined(AFX_STDAFX_H__41B89B6F_9399_11D2_9623_00C04F8EE628__INCLUDED)
|
44
mp/src/utils/sapi51/Samples/CPP/Engines/SR/version.rc2
Normal file
44
mp/src/utils/sapi51/Samples/CPP/Engines/SR/version.rc2
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef _MAC
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,0,1
|
||||||
|
PRODUCTVERSION 1,0,0,1
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x1L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Comments", "\0"
|
||||||
|
VALUE "CompanyName", "Microsoft Corp.\0"
|
||||||
|
VALUE "FileDescription", "TTS SAMPLE ENGINE 5\0"
|
||||||
|
VALUE "FileVersion", "1, 0, 0, 1\0"
|
||||||
|
VALUE "InternalName", "TTSSAMPLEENG5\0"
|
||||||
|
VALUE "LegalCopyright", "Copyright (c) Microsoft Corporation. All rights reserved.\0"
|
||||||
|
VALUE "LegalTrademarks", "\0"
|
||||||
|
VALUE "OriginalFilename", "ttseng.dll\0"
|
||||||
|
VALUE "PrivateBuild", "\0"
|
||||||
|
VALUE "ProductName", "Microsoft Corp. SAPI5 samples\0"
|
||||||
|
VALUE "ProductVersion", "1, 0, 0, 1\0"
|
||||||
|
VALUE "SpecialBuild", "\0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // !_MAC
|
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/anglais.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/anglais.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/as.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/as.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/blah.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/blah.wav
Normal file
Binary file not shown.
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/default.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/default.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/enter.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/enter.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/have.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/have.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/he.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/he.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/here.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/here.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/je.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/je.wav
Normal file
Binary file not shown.
187
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/mkvoice.cpp
Normal file
187
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/mkvoice.cpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* mkvoice.cpp *
|
||||||
|
*-------------*
|
||||||
|
* This application assembles a simple voice font for the sample TTS engine.
|
||||||
|
*Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include <ttseng_i.c>
|
||||||
|
#include <direct.h>
|
||||||
|
|
||||||
|
int wmain(int argc, WCHAR* argv[])
|
||||||
|
{
|
||||||
|
USES_CONVERSION;
|
||||||
|
static const DWORD dwVersion = { 1 };
|
||||||
|
ULONG ulNumWords = 0;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
//--- Check args
|
||||||
|
if( argc != 4 )
|
||||||
|
{
|
||||||
|
printf( "%s", "Usage: > mkvoice [[in]word list file] [[out]voice file] [voice name]\n" );
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
::CoInitialize( NULL );
|
||||||
|
|
||||||
|
//--- Open word list file and create output voice file
|
||||||
|
//--- _wfopen is not supported on Win9x, so use fopen.
|
||||||
|
FILE* hWordList = fopen( W2A(argv[1]), "r" );
|
||||||
|
FILE* hVoiceFile = fopen( W2A(argv[2]), "wb" );
|
||||||
|
|
||||||
|
if( hWordList && hVoiceFile )
|
||||||
|
{
|
||||||
|
//--- Write file version and leave space for word count
|
||||||
|
if( !fwrite( &dwVersion, sizeof(dwVersion), 1, hVoiceFile ) ||
|
||||||
|
fseek( hVoiceFile, 4, SEEK_CUR ) )
|
||||||
|
{
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Get each entry
|
||||||
|
WCHAR WordFileName[MAX_PATH];
|
||||||
|
while( SUCCEEDED( hr ) && fgetws( WordFileName, MAX_PATH, hWordList ) )
|
||||||
|
{
|
||||||
|
ULONG ulTextLen = wcslen( WordFileName );
|
||||||
|
if( WordFileName[ulTextLen-1] == '\n' )
|
||||||
|
{
|
||||||
|
WordFileName[--ulTextLen] = NULL;
|
||||||
|
}
|
||||||
|
//--- Include NULL character when writing to the file
|
||||||
|
ulTextLen = (ulTextLen+1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
if( fwrite( &ulTextLen, sizeof(ulTextLen), 1, hVoiceFile ) &&
|
||||||
|
fwrite( WordFileName, ulTextLen, 1, hVoiceFile ) )
|
||||||
|
{
|
||||||
|
++ulNumWords;
|
||||||
|
//--- Open the wav data
|
||||||
|
ISpStream* pStream;
|
||||||
|
wcscat( WordFileName, L".wav" );
|
||||||
|
hr = SPBindToFile( WordFileName, SPFM_OPEN_READONLY, &pStream );
|
||||||
|
if( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
CSpStreamFormat Fmt;
|
||||||
|
Fmt.AssignFormat(pStream);
|
||||||
|
if( Fmt.ComputeFormatEnum() == SPSF_11kHz16BitMono )
|
||||||
|
{
|
||||||
|
STATSTG Stat;
|
||||||
|
hr = pStream->Stat( &Stat, STATFLAG_NONAME );
|
||||||
|
ULONG ulNumBytes = Stat.cbSize.LowPart;
|
||||||
|
|
||||||
|
//--- Write the number of audio bytes
|
||||||
|
if( SUCCEEDED( hr ) &&
|
||||||
|
fwrite( &ulNumBytes, sizeof(ulNumBytes), 1, hVoiceFile ) )
|
||||||
|
{
|
||||||
|
BYTE* Buff = (BYTE*)alloca( ulNumBytes );
|
||||||
|
if( SUCCEEDED( hr = pStream->Read( Buff, ulNumBytes, NULL ) ) )
|
||||||
|
{
|
||||||
|
//--- Write the audio samples
|
||||||
|
if( !fwrite( Buff, 1, ulNumBytes, hVoiceFile ) )
|
||||||
|
{
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf( "Input file: %s has wrong wav format.", WordFileName );
|
||||||
|
}
|
||||||
|
pStream->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Write word count
|
||||||
|
if( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
if( fseek( hVoiceFile, sizeof(dwVersion), SEEK_SET ) ||
|
||||||
|
!fwrite( &ulNumWords, sizeof(ulNumWords), 1, hVoiceFile ) )
|
||||||
|
{
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Register the new voice file
|
||||||
|
// The section below shows how to programatically create a token for
|
||||||
|
// the new voice and set its attributes.
|
||||||
|
if( SUCCEEDED( hr ) )
|
||||||
|
{
|
||||||
|
CComPtr<ISpObjectToken> cpToken;
|
||||||
|
CComPtr<ISpDataKey> cpDataKeyAttribs;
|
||||||
|
hr = SpCreateNewTokenEx(
|
||||||
|
SPCAT_VOICES,
|
||||||
|
argv[3],
|
||||||
|
&CLSID_SampleTTSEngine,
|
||||||
|
L"Sample TTS Voice",
|
||||||
|
0x409,
|
||||||
|
L"Sample TTS Voice",
|
||||||
|
&cpToken,
|
||||||
|
&cpDataKeyAttribs);
|
||||||
|
|
||||||
|
//--- Set additional attributes for searching and the path to the
|
||||||
|
// voice data file we just created.
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpDataKeyAttribs->SetStringValue(L"Gender", L"Male");
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpDataKeyAttribs->SetStringValue(L"Name", L"SampleTTSVoice");
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpDataKeyAttribs->SetStringValue(L"Language", L"409");
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpDataKeyAttribs->SetStringValue(L"Age", L"Adult");
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpDataKeyAttribs->SetStringValue(L"Vendor", L"Microsoft");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- _wfullpath is not supported on Win9x, so use _fullpath.
|
||||||
|
CHAR szFullPath[MAX_PATH * 2];
|
||||||
|
if (SUCCEEDED(hr) && _fullpath(szFullPath, W2A(argv[2]), sizeof(szFullPath)/sizeof(szFullPath[0])) == NULL)
|
||||||
|
{
|
||||||
|
hr = SPERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
USES_CONVERSION;
|
||||||
|
hr = cpToken->SetStringValue(L"VoiceData", A2W(szFullPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Cleanup
|
||||||
|
if( hWordList )
|
||||||
|
{
|
||||||
|
fclose( hWordList );
|
||||||
|
}
|
||||||
|
if( hVoiceFile )
|
||||||
|
{
|
||||||
|
fclose( hVoiceFile );
|
||||||
|
}
|
||||||
|
::CoUninitialize();
|
||||||
|
}
|
||||||
|
return FAILED( hr );
|
||||||
|
}
|
||||||
|
|
125
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/mkvoice.dsp
Normal file
125
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/mkvoice.dsp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="mkvoice" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=mkvoice - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "mkvoice.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "mkvoice.mak" CFG="mkvoice - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "mkvoice - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "mkvoice - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "mkvoice - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\..\ddk\include" /I "..\..\..\..\..\include" /I "..\..\..\..\..\..\ddk\include" /I "..\..\..\include" /I "..\\" /I "..\engines\tts" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib advapi32.lib ole32.lib uuid.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\..\lib\i386"
|
||||||
|
# Begin Special Build Tool
|
||||||
|
TargetDir=.\Release
|
||||||
|
SOURCE="$(InputPath)"
|
||||||
|
PostBuild_Desc=Build and register voice file
|
||||||
|
PostBuild_Cmds=$(TargetDir)\mkvoice.exe wordlist.txt SampleVoice.vce SampleTTSVoice
|
||||||
|
# End Special Build Tool
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "mkvoice - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\..\ddk\include" /I "..\..\..\..\..\include" /I "..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib advapi32.lib ole32.lib uuid.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\..\lib\i386"
|
||||||
|
# Begin Special Build Tool
|
||||||
|
TargetDir=.\Debug
|
||||||
|
SOURCE="$(InputPath)"
|
||||||
|
PostBuild_Desc=Build and register voice file
|
||||||
|
PostBuild_Cmds=$(TargetDir)\mkvoice.exe wordlist.txt SampleVoice.vce SampleTTSVoice
|
||||||
|
# End Special Build Tool
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "mkvoice - Win32 Release"
|
||||||
|
# Name "mkvoice - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\mkvoice.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\StdAfx.cpp
|
||||||
|
# ADD CPP /Yc"stdafx.h"
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\StdAfx.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ReadMe.txt
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
@ -0,0 +1 @@
|
|||||||
|
#include "version.rc2"
|
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/parler.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/parler.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/peut.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/peut.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/said.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/said.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/sample.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/sample.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/selected.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/selected.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/she.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/she.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/speak.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/speak.wav
Normal file
Binary file not shown.
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/spoken.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/spoken.wav
Normal file
Binary file not shown.
@ -0,0 +1,9 @@
|
|||||||
|
// stdafx.cpp : source file that includes just the standard includes
|
||||||
|
// mkvoice.pch will be the pre-compiled header
|
||||||
|
// stdafx.obj will contain the pre-compiled type information
|
||||||
|
//Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
// TODO: reference any additional headers you need in STDAFX.H
|
||||||
|
// and not in this file
|
27
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/stdafx.h
Normal file
27
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/stdafx.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// stdafx.h : include file for standard system include files,
|
||||||
|
// or project specific include files that are used frequently, but
|
||||||
|
// are changed infrequently
|
||||||
|
//
|
||||||
|
|
||||||
|
#if !defined(AFX_STDAFX_H__152AD93A_F366_47F7_B0EF_5E609435ECBB__INCLUDED_)
|
||||||
|
#define AFX_STDAFX_H__152AD93A_F366_47F7_B0EF_5E609435ECBB__INCLUDED_
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif // _MSC_VER > 1000
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
#endif // WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <atlbase.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <SPHelper.h>
|
||||||
|
#include <ttseng.h>
|
||||||
|
|
||||||
|
// TODO: reference additional headers your program requires here
|
||||||
|
|
||||||
|
//{{AFX_INSERT_LOCATION}}
|
||||||
|
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||||
|
|
||||||
|
#endif // !defined(AFX_STDAFX_H__152AD93A_F366_47F7_B0EF_5E609435ECBB__INCLUDED_)
|
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/text.wav
Normal file
BIN
mp/src/utils/sapi51/Samples/CPP/Engines/TTS/MkVoice/text.wav
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user