| File: Internal\SapiInterop\SapiRecognizer.cs | Web Access |
| Project: src\runtime\src\libraries\System.Speech\src\System.Speech.csproj (System.Speech) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Runtime.InteropServices; using System.Speech.Internal.ObjectTokens; using System.Speech.Recognition; namespace System.Speech.Internal.SapiInterop { internal class SapiRecognizer : IDisposable { #region Constructors internal SapiRecognizer(RecognizerType type) { ISpRecognizer recognizer; try { if (type == RecognizerType.InProc) { recognizer = (ISpRecognizer)new SpInprocRecognizer(); } else { recognizer = (ISpRecognizer)new SpSharedRecognizer(); } _isSap53 = recognizer is ISpRecognizer2; } catch (COMException e) { throw RecognizerBase.ExceptionFromSapiCreateRecognizerError(e); } // Back out if the recognizer we have SAPI 5.1 if (!IsSapi53 && System.Threading.Thread.CurrentThread.GetApartmentState() == System.Threading.ApartmentState.STA) { // must be recreated on a different thread Marshal.ReleaseComObject(recognizer); _proxy = new SapiProxy.MTAThread(type); } else { _proxy = new SapiProxy.PassThrough(recognizer); } } public void Dispose() { if (!_disposed) { _proxy.Dispose(); _disposed = true; } GC.SuppressFinalize(this); } #endregion #region Internal Methods // ISpProperties Methods internal void SetPropertyNum(string name, int value) { _proxy.Invoke2(delegate { SetProperty(_proxy.Recognizer, name, value); }); } internal int GetPropertyNum(string name) { return (int)_proxy.Invoke(delegate { return GetProperty(_proxy.Recognizer, name, true); })!; } internal void SetPropertyString(string name, string value) { _proxy.Invoke2(delegate { SetProperty(_proxy.Recognizer, name, value); }); } internal string GetPropertyString(string name) { return (string)_proxy.Invoke(delegate { return GetProperty(_proxy.Recognizer, name, false); })!; } // ISpRecognizer Methods internal void SetRecognizer(ISpObjectToken recognizer) { try { _proxy.Invoke2(delegate { _proxy.Recognizer.SetRecognizer(recognizer); }); } catch (InvalidCastException) { // The Interop layer maps the SAPI error that an interface cannot by QI to an Invalid cast exception // Map the InvalidCastException throw new PlatformNotSupportedException(SR.Get(SRID.NotSupportedWithThisVersionOfSAPI)); } } internal RecognizerInfo GetRecognizerInfo() { ISpObjectToken sapiObjectToken; return (RecognizerInfo)_proxy.Invoke(delegate { RecognizerInfo? recognizerInfo; _proxy.Recognizer.GetRecognizer(out sapiObjectToken); IntPtr sapiTokenId; try { sapiObjectToken.GetId(out sapiTokenId); string tokenId = Marshal.PtrToStringUni(sapiTokenId)!; recognizerInfo = RecognizerInfo.Create(ObjectToken.Open(null, tokenId, false)!); if (recognizerInfo == null) { throw new InvalidOperationException(SR.Get(SRID.RecognizerNotFound)); } Marshal.FreeCoTaskMem(sapiTokenId); } finally { Marshal.ReleaseComObject(sapiObjectToken); } return recognizerInfo; })!; } internal void SetInput(object? input, bool allowFormatChanges) { _proxy.Invoke2(delegate { _proxy.Recognizer.SetInput(input, allowFormatChanges); }); } internal SapiRecoContext CreateRecoContext() { ISpRecoContext context; return (SapiRecoContext)_proxy.Invoke(delegate { _proxy.Recognizer.CreateRecoContext(out context); return new SapiRecoContext(context, _proxy); })!; } internal SPRECOSTATE GetRecoState() { SPRECOSTATE state; return (SPRECOSTATE)_proxy.Invoke(delegate { _proxy.Recognizer.GetRecoState(out state); return state; })!; } internal void SetRecoState(SPRECOSTATE state) { _proxy.Invoke2(delegate { _proxy.Recognizer.SetRecoState(state); }); } internal SPRECOGNIZERSTATUS GetStatus() { SPRECOGNIZERSTATUS status; return (SPRECOGNIZERSTATUS)_proxy.Invoke(delegate { _proxy.Recognizer.GetStatus(out status); return status; })!; } internal IntPtr GetFormat(SPSTREAMFORMATTYPE WaveFormatType) { return (IntPtr)_proxy.Invoke(delegate { Guid formatId; IntPtr ppCoMemWFEX; _proxy.Recognizer.GetFormat(WaveFormatType, out formatId, out ppCoMemWFEX); return ppCoMemWFEX; })!; } internal SAPIErrorCodes EmulateRecognition(string? phrase) { object displayAttributes = " "; // Passing a null object here doesn't work because EmulateRecognition doesn't handle VT_EMPTY return (SAPIErrorCodes)_proxy.Invoke(delegate { return _proxy.SapiSpeechRecognizer.EmulateRecognition(phrase, ref displayAttributes, 0); })!; } internal SAPIErrorCodes EmulateRecognition(ISpPhrase iSpPhrase, uint dwCompareFlags) { return (SAPIErrorCodes)_proxy.Invoke(delegate { return _proxy.Recognizer2.EmulateRecognitionEx(iSpPhrase, dwCompareFlags); })!; } #endregion #region Internal Properties internal bool IsSapi53 { get { return _isSap53; } } #endregion #region Internal Types internal enum RecognizerType { InProc, Shared } #endregion #region Private Methods private static void SetProperty(ISpRecognizer sapiRecognizer, string name, object value) { SAPIErrorCodes errorCode; if (value is int) { errorCode = (SAPIErrorCodes)sapiRecognizer.SetPropertyNum(name, (int)value); } else { errorCode = (SAPIErrorCodes)sapiRecognizer.SetPropertyString(name, (string)value); } if (errorCode == SAPIErrorCodes.S_FALSE) { throw new KeyNotFoundException(SR.Get(SRID.RecognizerSettingNotSupported)); } else if (errorCode < SAPIErrorCodes.S_OK) { throw RecognizerBase.ExceptionFromSapiCreateRecognizerError(new COMException(SR.Get(SRID.RecognizerSettingUpdateError), (int)errorCode)); } } private static object GetProperty(ISpRecognizer sapiRecognizer, string name, bool integer) { SAPIErrorCodes errorCode; object? result = null; if (integer) { int value; errorCode = (SAPIErrorCodes)sapiRecognizer.GetPropertyNum(name, out value); result = value; } else { string value; errorCode = (SAPIErrorCodes)sapiRecognizer.GetPropertyString(name, out value); result = value; } if (errorCode == SAPIErrorCodes.S_FALSE) { throw new KeyNotFoundException(SR.Get(SRID.RecognizerSettingNotSupported)); } else if (errorCode < SAPIErrorCodes.S_OK) { throw RecognizerBase.ExceptionFromSapiCreateRecognizerError(new COMException(SR.Get(SRID.RecognizerSettingUpdateError), (int)errorCode)); } return result; } #endregion #region Private Fields private SapiProxy _proxy; private bool _disposed; private bool _isSap53; #endregion } }