Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

556 lines
14 KiB

  1. //
  2. // lmlattice.cpp
  3. //
  4. // implelementation of ITfLMLattice object, IEnumTfLatticeElements object
  5. //
  6. #include "private.h"
  7. #include "sapilayr.h"
  8. #include "lmlattic.h"
  9. //
  10. // CLMLattice
  11. //
  12. //
  13. // ctor / dtor
  14. CLMLattice::CLMLattice(CSapiIMX *p_tip, IUnknown *pResWrap)
  15. {
  16. m_cpResWrap = pResWrap;
  17. m_pTip = p_tip;
  18. if (m_pTip)
  19. {
  20. m_pTip->AddRef();
  21. }
  22. m_cRef = 1;
  23. }
  24. CLMLattice::~CLMLattice()
  25. {
  26. if (m_pTip)
  27. {
  28. m_pTip->Release();
  29. }
  30. }
  31. // IUnknown
  32. HRESULT CLMLattice::QueryInterface(REFIID riid, void **ppvObj)
  33. {
  34. HRESULT hr;
  35. Assert(ppvObj);
  36. if (IsEqualIID(riid, IID_IUnknown)
  37. || IsEqualIID(riid, IID_ITfLMLattice))
  38. {
  39. *ppvObj = this;
  40. hr = S_OK;
  41. this->m_cRef++;
  42. }
  43. else
  44. {
  45. *ppvObj = NULL;
  46. hr = E_NOINTERFACE;
  47. }
  48. return hr;
  49. }
  50. ULONG CLMLattice::AddRef(void)
  51. {
  52. this->m_cRef++;
  53. return this->m_cRef;
  54. }
  55. ULONG CLMLattice::Release(void)
  56. {
  57. this->m_cRef--;
  58. if (this->m_cRef > 0)
  59. {
  60. return this->m_cRef;
  61. }
  62. delete this;
  63. return 0;
  64. }
  65. // ITfLMLattice
  66. HRESULT CLMLattice::QueryType(REFGUID refguidType, BOOL *pfSupported)
  67. {
  68. HRESULT hr = E_INVALIDARG;
  69. if (pfSupported)
  70. {
  71. *pfSupported = IsEqualGUID(refguidType, GUID_LMLATTICE_VER1_0);
  72. if (*pfSupported)
  73. hr = S_OK;
  74. }
  75. return hr;
  76. }
  77. HRESULT CLMLattice::EnumLatticeElements( DWORD dwFrameStart, REFGUID refguidType, IEnumTfLatticeElements **ppEnum)
  78. {
  79. if (!ppEnum)
  80. return E_INVALIDARG;
  81. *ppEnum = NULL;
  82. if (!IsEqualGUID(refguidType, GUID_LMLATTICE_VER1_0))
  83. return E_INVALIDARG;
  84. HRESULT hr = E_FAIL;
  85. // get alternates and cache the returned cotaskmem
  86. ULONG ulcMaxAlt = m_pTip->_GetMaxAlternates();
  87. ISpPhraseAlt **ppAlt = NULL;
  88. CComPtr<IServiceProvider> cpServicePrv;
  89. CComPtr<ISpRecoResult> cpRecoResult;
  90. CRecoResultWrap *pWrap = NULL;
  91. ULONG ulStartInWrp, ulNumInWrp;
  92. // QI the service provider first then get to the sapi interface
  93. //
  94. hr = m_cpResWrap->QueryInterface(IID_IServiceProvider, (void **)&cpServicePrv);
  95. if (SUCCEEDED(hr))
  96. {
  97. hr = m_cpResWrap->QueryInterface(IID_PRIV_RESULTWRAP, (void **)&pWrap);
  98. }
  99. if (SUCCEEDED(hr))
  100. {
  101. hr = cpServicePrv->QueryService(GUID_NULL, IID_ISpRecoResult, (void **)&cpRecoResult);
  102. }
  103. ulStartInWrp = pWrap->GetStart();
  104. ulNumInWrp = pWrap->GetNumElements();
  105. if ( SUCCEEDED(hr))
  106. {
  107. // Get the Alternates for current RecoResult.
  108. ppAlt = (ISpPhraseAlt **)cicMemAlloc(ulcMaxAlt * sizeof(ISpPhraseAlt *));
  109. if (ppAlt)
  110. {
  111. hr = cpRecoResult->GetAlternates(
  112. ulStartInWrp,
  113. ulNumInWrp,
  114. ulcMaxAlt,
  115. ppAlt, /* [out] ISpPhraseAlt **ppPhrases, */
  116. &ulcMaxAlt /* [out] ULONG *pcPhrasesReturned */
  117. );
  118. }
  119. else
  120. hr = E_OUTOFMEMORY;
  121. }
  122. // OK now create an instance of enumerator
  123. CEnumLatticeElements *pEnumLE = NULL;
  124. if ( SUCCEEDED(hr) )
  125. {
  126. pEnumLE = new CEnumLatticeElements(dwFrameStart);
  127. if (!pEnumLE)
  128. hr = E_OUTOFMEMORY;
  129. if (S_OK == hr)
  130. {
  131. for ( ULONG i=0; i<ulcMaxAlt; i++)
  132. {
  133. SPPHRASE *pPhrase = NULL;
  134. ULONG ulStart, ulNum;
  135. ULONG ulStartInPar, ulNumInParent;
  136. ppAlt[i]->GetPhrase(&pPhrase);
  137. ppAlt[i]->GetAltInfo(NULL, &ulStartInPar, &ulNumInParent, &ulNum);
  138. if ( (ulStartInPar >= ulStartInWrp) && (ulStartInPar+ulNumInParent <= ulStartInWrp+ulNumInWrp) )
  139. {
  140. // This is a valid alternate
  141. if( SUCCEEDED(hr) )
  142. {
  143. ulStart = ulStartInPar;
  144. hr = pEnumLE->_InitFromPhrase(pPhrase, ulStart, ulNum);
  145. }
  146. }
  147. if (pPhrase)
  148. {
  149. CoTaskMemFree(pPhrase);
  150. }
  151. }
  152. }
  153. }
  154. if (S_OK == hr)
  155. {
  156. hr = pEnumLE->QueryInterface(IID_IEnumTfLatticeElements, (void **)ppEnum);
  157. }
  158. SafeRelease(pEnumLE);
  159. if ( ppAlt )
  160. {
  161. // Release references to alternate phrases.
  162. for (int i = 0; i < (int)ulcMaxAlt; i++)
  163. {
  164. if (NULL != (ppAlt)[i])
  165. {
  166. ((ppAlt)[i])->Release();
  167. }
  168. }
  169. cicMemFree(ppAlt);
  170. }
  171. return hr;
  172. }
  173. //
  174. // CEnumLatticeElements
  175. //
  176. //
  177. // ctor / dtor
  178. CEnumLatticeElements::CEnumLatticeElements(DWORD dwFrameStart)
  179. {
  180. m_dwFrameStart = dwFrameStart;
  181. m_ulCur = (ULONG)-1;
  182. m_ulTotal = 0;
  183. m_cRef = 1;
  184. }
  185. CEnumLatticeElements::~CEnumLatticeElements()
  186. {
  187. // clean up the lattice elements here
  188. int ulCount;
  189. TF_LMLATTELEMENT * pLE;
  190. ulCount = (int) Count( );
  191. TraceMsg(TF_GENERAL, "CEnumLatticeElements::~CEnumLatticeElements: ulCount=%d", ulCount);
  192. if (ulCount)
  193. {
  194. for (int i = 0; i < ulCount; i++)
  195. {
  196. pLE = GetPtr(i);
  197. if ( pLE && pLE->bstrText)
  198. {
  199. ::SysFreeString(pLE->bstrText);
  200. pLE->bstrText=0;
  201. }
  202. }
  203. }
  204. }
  205. // IUnknown
  206. HRESULT CEnumLatticeElements::QueryInterface(REFIID riid, void **ppvObj)
  207. {
  208. HRESULT hr;
  209. Assert(ppvObj);
  210. if (IsEqualIID(riid, IID_IUnknown)
  211. || IsEqualIID(riid, IID_IEnumTfLatticeElements))
  212. {
  213. *ppvObj = this;
  214. hr = S_OK;
  215. this->m_cRef++;
  216. }
  217. else
  218. {
  219. *ppvObj = NULL;
  220. hr = E_NOINTERFACE;
  221. }
  222. return hr;
  223. }
  224. ULONG CEnumLatticeElements::AddRef(void)
  225. {
  226. this->m_cRef++;
  227. return this->m_cRef;
  228. }
  229. ULONG CEnumLatticeElements::Release(void)
  230. {
  231. this->m_cRef--;
  232. if (this->m_cRef > 0)
  233. {
  234. return this->m_cRef;
  235. }
  236. delete this;
  237. return 0;
  238. }
  239. // ITfEnumLatticeElements
  240. HRESULT CEnumLatticeElements::Clone(IEnumTfLatticeElements **ppEnum)
  241. {
  242. HRESULT hr = E_INVALIDARG;
  243. if (ppEnum)
  244. {
  245. CEnumLatticeElements *pele = new CEnumLatticeElements(m_dwFrameStart);
  246. if ( !pele )
  247. return E_OUTOFMEMORY;
  248. if (pele->Append(Count()))
  249. {
  250. for (int i = 0; i < Count(); i++)
  251. {
  252. *(pele->GetPtr(i)) = *GetPtr(i);
  253. Assert((pele->GetPtr(i))->bstrText);
  254. (pele->GetPtr(i))->bstrText = SysAllocString(GetPtr(i)->bstrText);
  255. }
  256. pele->m_dwFrameStart = m_dwFrameStart;
  257. hr = pele->QueryInterface(IID_IEnumTfLatticeElements, (void **)ppEnum);
  258. }
  259. else
  260. {
  261. delete pele;
  262. hr = E_OUTOFMEMORY;
  263. }
  264. }
  265. return hr;
  266. }
  267. HRESULT CEnumLatticeElements::Next(ULONG ulCount, TF_LMLATTELEMENT *rgsElements, ULONG *pcFetched)
  268. {
  269. if (ulCount == 0
  270. || rgsElements == NULL
  271. || pcFetched == NULL
  272. )
  273. return E_INVALIDARG;
  274. // find the start position
  275. if (m_dwFrameStart == -1)
  276. {
  277. m_ulCur = m_dwFrameStart = 0;
  278. }
  279. else
  280. {
  281. if (m_ulCur == (ULONG)-1)
  282. {
  283. _Find(m_dwFrameStart, &m_ulCur);
  284. }
  285. }
  286. if (m_ulCur >= m_ulTotal)
  287. {
  288. // no more elements but OK
  289. *pcFetched = 0;
  290. }
  291. else
  292. {
  293. // something to return
  294. for (ULONG ul = m_ulCur;
  295. ul < m_ulTotal && ul - m_ulCur < ulCount;
  296. ul++)
  297. {
  298. rgsElements[ul-m_ulCur] = *GetPtr(ul);
  299. }
  300. *pcFetched = ul - m_ulCur;
  301. }
  302. return S_OK;
  303. }
  304. HRESULT CEnumLatticeElements::Reset()
  305. {
  306. m_ulCur = (ULONG)-1;
  307. return S_OK;
  308. }
  309. HRESULT CEnumLatticeElements::Skip(ULONG ulCount)
  310. {
  311. // find the start position
  312. if (m_dwFrameStart == -1)
  313. {
  314. m_ulCur = m_dwFrameStart = 0;
  315. }
  316. else
  317. {
  318. if (m_ulCur == (ULONG)-1)
  319. {
  320. _Find(m_dwFrameStart, &m_ulCur);
  321. }
  322. }
  323. m_ulCur += ulCount;
  324. if (m_ulCur > m_ulTotal)
  325. m_ulCur = m_ulTotal;
  326. return E_NOTIMPL;
  327. }
  328. //
  329. // internal APIs
  330. //
  331. HRESULT CEnumLatticeElements::_InitFromPhrase
  332. (
  333. SPPHRASE *pPhrase,
  334. ULONG ulStartElem,
  335. ULONG ulNumElem
  336. )
  337. {
  338. Assert(pPhrase);
  339. if ( pPhrase == NULL)
  340. return E_INVALIDARG;
  341. HRESULT hr = S_OK;
  342. // allocate the initial slots
  343. if (!Append(ulNumElem))
  344. {
  345. hr = E_OUTOFMEMORY;
  346. }
  347. if (S_OK == hr)
  348. {
  349. long lEndElem;
  350. long indexOrgList;
  351. long indexNewList;
  352. lEndElem = min(pPhrase->Rule.ulCountOfElements, ulStartElem + ulNumElem);
  353. lEndElem --; // Real position ( offset from 0 ) for the last element
  354. indexNewList = Count( ) - 1;
  355. indexOrgList = indexNewList - ulNumElem;
  356. m_ulTotal += ulNumElem;
  357. TraceMsg(TF_GENERAL, "_InitFromPhrase: m_ulTotal=%d", m_ulTotal);
  358. // FutureConsider: ITN has to be considered here!
  359. for (long i=lEndElem; i>=(long)ulStartElem; i--)
  360. {
  361. TF_LMLATTELEMENT * pLE;
  362. // Compare all the elements in the Org list from End to start
  363. // with this new element's dwFrameStart,
  364. // If dwFrameStart of the element in Org list is larger than(or equal to)
  365. // this element's dwFrameStart, just move the org element
  366. // to the current available position in the new list.
  367. // until we find an element in the org list whose dwFrameStart is less than
  368. // this element's dwFrameStart. we need to move this element to the
  369. // new current available item in the new list.
  370. // Current available position in the new list is from End to Start.
  371. while ( (indexOrgList >=0) && (indexNewList >=0) && (S_OK == hr) )
  372. {
  373. pLE = GetPtr(indexOrgList);
  374. if (pLE)
  375. {
  376. if ( pLE->dwFrameStart >= pPhrase->pElements[i].ulAudioTimeOffset )
  377. {
  378. // Move this Org element to a new postion in new List.
  379. TF_LMLATTELEMENT * pNewLE;
  380. pNewLE = GetPtr(indexNewList);
  381. if ( pNewLE)
  382. {
  383. pNewLE->dwFrameStart = pLE->dwFrameStart;
  384. pNewLE->dwFrameLen = pLE->dwFrameLen;
  385. pNewLE->dwFlags = pLE->dwFlags;
  386. pNewLE->iCost = pLE->iCost;
  387. pNewLE->bstrText = pLE->bstrText;
  388. pLE->dwFrameStart = 0;
  389. pLE->dwFrameLen = 0;
  390. pLE->dwFlags = 0;
  391. pLE->iCost = 0;
  392. pLE->bstrText = 0;
  393. }
  394. // update the index position in both org and new list
  395. indexNewList --;
  396. indexOrgList --;
  397. }
  398. else
  399. {
  400. // current element from this phrase should be moved to the new list
  401. break;
  402. }
  403. }
  404. else
  405. {
  406. TraceMsg(TF_GENERAL, "CEnumLatticeElements::_InitFromPhrase: pLE is NULL");
  407. hr = E_FAIL;
  408. break;
  409. }
  410. } //while
  411. if ( (S_OK == hr) && (indexNewList >=0) )
  412. {
  413. pLE = GetPtr(indexNewList);
  414. if (pLE)
  415. {
  416. pLE->dwFrameStart = pPhrase->pElements[i].ulAudioTimeOffset;
  417. pLE->dwFrameLen = pPhrase->pElements[i].ulAudioSizeTime;
  418. pLE->dwFlags = 0; // for now
  419. pLE->iCost = pPhrase->pElements[i].ActualConfidence;
  420. pLE->bstrText = SysAllocString(pPhrase->pElements[i].pszDisplayText);
  421. TraceMsg(TF_GENERAL, "i=%d, dwFramStart=%d bstrText=%S", i, pLE->dwFrameStart, pLE->bstrText);
  422. indexNewList--;
  423. }
  424. }
  425. } // for
  426. } // if
  427. return hr;
  428. }
  429. //
  430. // _Find()
  431. //
  432. // slightly modified version of array find
  433. //
  434. ULONG CEnumLatticeElements::_Find(DWORD dwFrame, ULONG *pul)
  435. {
  436. int iMatch = -1;
  437. int iMid = -1;
  438. int iMin = 0;
  439. int iMax = _cElems;
  440. while(iMin < iMax)
  441. {
  442. iMid = (iMin + iMax) / 2;
  443. DWORD dwCur = GetPtr(iMid)->dwFrameStart;
  444. if (dwFrame < dwCur)
  445. {
  446. iMax = iMid;
  447. }
  448. else if (dwFrame > dwCur)
  449. {
  450. iMin = iMid + 1;
  451. }
  452. else
  453. {
  454. iMatch = iMid;
  455. break;
  456. }
  457. }
  458. if (pul)
  459. {
  460. if ((iMatch == -1) && (iMid >= 0))
  461. {
  462. if (dwFrame < GetPtr(iMid)->dwFrameStart)
  463. iMid--;
  464. }
  465. *pul = iMid;
  466. }
  467. return iMatch;
  468. }