Fixing Microsoft speech SDK based on the official Valve tutorial

This commit is contained in:
ScrewTSW 2018-09-16 12:10:29 +02:00
parent 0d8dceea43
commit 9beee1df69
940 changed files with 252064 additions and 0 deletions

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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;
};
}

View 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 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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 */

View 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 */

View 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 -------------------------------------------

View 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

View File

@ -0,0 +1,2 @@
#define IDC_VERSION_EDIT 10000
#define IDD_COMPONENT_VERSION_DLG 10001

View 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 */

View 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

View 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>

View 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>

View 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

View 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>

File diff suppressed because it is too large Load Diff

View 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

View 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>

File diff suppressed because it is too large Load Diff

View 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

View 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 );

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View 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

File diff suppressed because it is too large Load Diff

View 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>

View 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>

View 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

View 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 */

View 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

View 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.
/////////////////////////////////////////////////////////////////////////////

View 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 */

View 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

View 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

View 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 */

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View 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

View 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_)

View 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 */

View 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 */

File diff suppressed because it is too large Load Diff

View 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 */

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

View 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

View 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

View 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);
}

View File

@ -0,0 +1,9 @@
; sreng.def : Declares the module parameters.
LIBRARY "sreng.DLL"
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE

View 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

View 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;
};
};

View 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

View 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}'
}
}
}
}
}
}
}
}
}

View 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;
}

View 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);
};

View 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}'
}
}
}

View 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) );
}

View 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;
};

View 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}'
}
}
}

File diff suppressed because it is too large Load Diff

View 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 );
};

View 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;
}

View 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);
};

View 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}'
}
}
}

View 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"

View 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>

View 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)

View 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

View 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 );
}

View 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

View File

@ -0,0 +1 @@
#include "version.rc2"

View File

@ -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

View 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_)

Some files were not shown because too many files have changed in this diff Show More