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.

720 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) 1998-1999 Microsoft Corporation
  6. //
  7. // File: mutetrk.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
  11. //
  12. // 4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX
  13. //
  14. // We disable this because we use exceptions and do *not* specify -GX (USE_NATIVE_EH in
  15. // sources).
  16. //
  17. // The one place we use exceptions is around construction of objects that call
  18. // InitializeCriticalSection. We guarantee that it is safe to use in this case with
  19. // the restriction given by not using -GX (automatic objects in the call chain between
  20. // throw and handler are not destructed). Turning on -GX buys us nothing but +10% to code
  21. // size because of the unwind code.
  22. //
  23. // Any other use of exceptions must follow these restrictions or -GX must be turned on.
  24. //
  25. // READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
  26. //
  27. #pragma warning(disable:4530)
  28. // MuteTrk.cpp : Implementation of CMuteTrack
  29. #include <objbase.h>
  30. #include "MuteTrk.h"
  31. #include "debug.h"
  32. #include "debug.h"
  33. #include "..\shared\Validate.h"
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CMuteTrack
  36. CMuteTrack::CMuteTrack() : m_bRequiresSave(0),
  37. m_cRef(1), m_fCSInitialized(FALSE)
  38. {
  39. InterlockedIncrement(&g_cComponent);
  40. ::InitializeCriticalSection( &m_CriticalSection );
  41. m_fCSInitialized = TRUE;
  42. }
  43. CMuteTrack::CMuteTrack(const CMuteTrack& rTrack, MUSIC_TIME mtStart, MUSIC_TIME mtEnd) :
  44. m_bRequiresSave(0),
  45. m_cRef(1), m_fCSInitialized(FALSE)
  46. {
  47. InterlockedIncrement(&g_cComponent);
  48. ::InitializeCriticalSection( &m_CriticalSection );
  49. m_fCSInitialized = TRUE;
  50. TListItem<MapSequence>* pSeqScan = rTrack.m_MapSequenceList.GetHead();
  51. for(; pSeqScan; pSeqScan = pSeqScan->GetNext())
  52. {
  53. MapSequence& rSeqScan = pSeqScan->GetItemValue();
  54. TListItem<MapSequence>* pNewSeq = new TListItem<MapSequence>;
  55. if (!pNewSeq) break;
  56. MapSequence& rNewSeq = pNewSeq->GetItemValue();
  57. rNewSeq.m_dwPChannel = rSeqScan.m_dwPChannel;
  58. TListItem<MuteMapping>* pScan = rSeqScan.m_Mappings.GetHead();
  59. TListItem<MuteMapping>* pPrevious = NULL;
  60. for(; pScan; pScan = pScan->GetNext())
  61. {
  62. MuteMapping& rScan = pScan->GetItemValue();
  63. if (rScan.m_mtTime < mtStart)
  64. {
  65. pPrevious = pScan;
  66. }
  67. else if (rScan.m_mtTime < mtEnd)
  68. {
  69. if (rScan.m_mtTime == mtStart)
  70. {
  71. pPrevious = NULL;
  72. }
  73. TListItem<MuteMapping>* pNew = new TListItem<MuteMapping>;
  74. if (pNew)
  75. {
  76. MuteMapping& rNew = pNew->GetItemValue();
  77. rNew.m_mtTime = rScan.m_mtTime - mtStart;
  78. rNew.m_dwPChannelMap = rScan.m_dwPChannelMap;
  79. rNew.m_fMute = rScan.m_fMute;
  80. rNewSeq.m_Mappings.AddTail(pNew);
  81. }
  82. }
  83. else break;
  84. }
  85. if (pPrevious)
  86. {
  87. TListItem<MuteMapping>* pNew = new TListItem<MuteMapping>;
  88. if (pNew)
  89. {
  90. MuteMapping& rNew = pNew->GetItemValue();
  91. rNew.m_mtTime = 0;
  92. rNew.m_dwPChannelMap = pPrevious->GetItemValue().m_dwPChannelMap;
  93. rNew.m_fMute = pPrevious->GetItemValue().m_fMute;
  94. rNewSeq.m_Mappings.AddHead(pNew);
  95. }
  96. }
  97. if (rNewSeq.m_Mappings.GetHead())
  98. {
  99. m_MapSequenceList.AddTail(pNewSeq);
  100. }
  101. else
  102. {
  103. delete pNewSeq;
  104. }
  105. }
  106. }
  107. CMuteTrack::~CMuteTrack()
  108. {
  109. if (m_fCSInitialized)
  110. {
  111. ::DeleteCriticalSection( &m_CriticalSection );
  112. }
  113. InterlockedDecrement(&g_cComponent);
  114. }
  115. void CMuteTrack::Clear()
  116. {
  117. m_MapSequenceList.CleanUp();
  118. }
  119. STDMETHODIMP CMuteTrack::QueryInterface(
  120. const IID &iid,
  121. void **ppv)
  122. {
  123. V_INAME(CMuteTrack::QueryInterface);
  124. V_REFGUID(iid);
  125. V_PTRPTR_WRITE(ppv);
  126. if (iid == IID_IUnknown || iid == IID_IDirectMusicTrack || iid == IID_IDirectMusicTrack8)
  127. {
  128. *ppv = static_cast<IDirectMusicTrack*>(this);
  129. }
  130. else if (iid == IID_IPersistStream)
  131. {
  132. *ppv = static_cast<IPersistStream*>(this);
  133. }
  134. else
  135. {
  136. *ppv = NULL;
  137. return E_NOINTERFACE;
  138. }
  139. reinterpret_cast<IUnknown*>(this)->AddRef();
  140. return S_OK;
  141. }
  142. STDMETHODIMP_(ULONG) CMuteTrack::AddRef()
  143. {
  144. return InterlockedIncrement(&m_cRef);
  145. }
  146. STDMETHODIMP_(ULONG) CMuteTrack::Release()
  147. {
  148. if (!InterlockedDecrement(&m_cRef))
  149. {
  150. delete this;
  151. return 0;
  152. }
  153. return m_cRef;
  154. }
  155. // CMuteTrack Methods
  156. HRESULT CMuteTrack::Init(
  157. /*[in]*/ IDirectMusicSegment* pSegment
  158. )
  159. {
  160. V_INAME(CMuteTrack::Init);
  161. V_INTERFACE(pSegment);
  162. return S_OK;
  163. }
  164. HRESULT CMuteTrack::InitPlay(
  165. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  166. /*[in]*/ IDirectMusicPerformance* pPerformance,
  167. /*[out]*/ void** ppStateData,
  168. /*[in]*/ DWORD dwTrackID,
  169. /*[in]*/ DWORD dwFlags
  170. )
  171. {
  172. EnterCriticalSection( &m_CriticalSection );
  173. LeaveCriticalSection( &m_CriticalSection );
  174. return S_OK;
  175. }
  176. HRESULT CMuteTrack::EndPlay(
  177. /*[in]*/ void* pStateData
  178. )
  179. {
  180. return S_OK;
  181. }
  182. HRESULT CMuteTrack::Play(
  183. /*[in]*/ void* pStateData,
  184. /*[in]*/ MUSIC_TIME mtStart,
  185. /*[in]*/ MUSIC_TIME mtEnd,
  186. /*[in]*/ MUSIC_TIME mtOffset,
  187. DWORD dwFlags,
  188. IDirectMusicPerformance* pPerf,
  189. IDirectMusicSegmentState* pSegState,
  190. DWORD dwVirtualID
  191. )
  192. {
  193. EnterCriticalSection( &m_CriticalSection );
  194. // For now: do nothing.
  195. LeaveCriticalSection( &m_CriticalSection );
  196. return DMUS_S_END;
  197. }
  198. HRESULT CMuteTrack::GetPriority(
  199. /*[out]*/ DWORD* pPriority
  200. )
  201. {
  202. return E_NOTIMPL;
  203. }
  204. HRESULT CMuteTrack::GetParam(
  205. REFGUID rCommandGuid,
  206. MUSIC_TIME mtTime,
  207. MUSIC_TIME* pmtNext,
  208. void *pData)
  209. {
  210. V_INAME(CMuteTrack::GetParam);
  211. V_PTR_WRITE_OPT(pmtNext,MUSIC_TIME);
  212. V_PTR_WRITE(pData,1);
  213. V_REFGUID(rCommandGuid);
  214. if (rCommandGuid != GUID_MuteParam) return DMUS_E_TYPE_UNSUPPORTED;
  215. HRESULT hr = S_OK;
  216. DMUS_MUTE_PARAM* pDMUS_MUTE_PARAM = (DMUS_MUTE_PARAM*) pData;
  217. MUSIC_TIME mtLength = 0;
  218. HRESULT hrMute = E_FAIL;
  219. EnterCriticalSection( &m_CriticalSection );
  220. // if (m_pSegment) hrMute = m_pSegment->GetLength(&mtLength);
  221. TListItem<MapSequence>* pSeqScan = m_MapSequenceList.GetHead();
  222. // Find a matching map sequence
  223. for (; pSeqScan; pSeqScan = pSeqScan->GetNext())
  224. {
  225. if (pSeqScan->GetItemValue().m_dwPChannel == pDMUS_MUTE_PARAM->dwPChannel) break;
  226. }
  227. if (pSeqScan)
  228. {
  229. // Find the maps directly before (or at) and directly after mtTime
  230. TListItem<MuteMapping>* pScan = pSeqScan->GetItemValue().m_Mappings.GetHead();
  231. TListItem<MuteMapping>* pPrevious = NULL;
  232. for( ; pScan; pScan = pScan->GetNext())
  233. {
  234. MUSIC_TIME mt = pScan->GetItemValue().m_mtTime;
  235. if (mt <= mtTime)
  236. {
  237. pPrevious = pScan;
  238. }
  239. /*
  240. // If we're at the end of the segment...
  241. else if (SUCCEEDED(hrMute) && mtTime == mtLength - 1 && mt == mtLength)
  242. {
  243. pPrevious = pScan;
  244. pScan = NULL;
  245. break;
  246. }
  247. */
  248. else
  249. {
  250. break;
  251. }
  252. }
  253. if (pPrevious)
  254. {
  255. pDMUS_MUTE_PARAM->dwPChannelMap = pPrevious->GetItemValue().m_dwPChannelMap;
  256. pDMUS_MUTE_PARAM->fMute = pPrevious->GetItemValue().m_fMute;
  257. //*pmtNext = (pScan) ? (pScan->GetItemValue().m_mtTime - mtTime) : 0; // RSW: bug 167740
  258. }
  259. else
  260. // Nothing in the list is <= mtTime, so return a map that maps to itself, and the time
  261. // of the first mapping in the list
  262. {
  263. pDMUS_MUTE_PARAM->dwPChannelMap = pDMUS_MUTE_PARAM->dwPChannel;
  264. pDMUS_MUTE_PARAM->fMute = FALSE;
  265. //*pmtNext = (pScan) ? (pScan->GetItemValue().m_mtTime - mtTime) : 0; // RSW: bug 167740
  266. }
  267. if (pmtNext)
  268. {
  269. if (pScan)
  270. {
  271. /*
  272. // If we have a mute at the end of the segment...
  273. if (SUCCEEDED(hrMute) && pScan->GetItemValue().m_mtTime >= mtLength)
  274. {
  275. *pmtNext = (mtLength - 1) - mtTime;
  276. }
  277. else
  278. */
  279. {
  280. *pmtNext = pScan->GetItemValue().m_mtTime - mtTime; // RSW: bug 167740
  281. }
  282. }
  283. else
  284. {
  285. /*
  286. if (SUCCEEDED(hrMute))
  287. {
  288. mtLength -= mtTime;
  289. if (mtLength < 0) mtLength = 0;
  290. }
  291. */
  292. *pmtNext = mtLength;
  293. }
  294. }
  295. }
  296. else
  297. {
  298. // assume something that maps to itself, with a next time of 0
  299. pDMUS_MUTE_PARAM->dwPChannelMap = pDMUS_MUTE_PARAM->dwPChannel;
  300. pDMUS_MUTE_PARAM->fMute = FALSE;
  301. if (pmtNext)
  302. {
  303. *pmtNext = 0;
  304. }
  305. hr = S_OK;
  306. }
  307. LeaveCriticalSection( &m_CriticalSection );
  308. return hr;
  309. }
  310. HRESULT CMuteTrack::SetParam(
  311. REFGUID rCommandGuid,
  312. MUSIC_TIME mtTime,
  313. void __RPC_FAR *pData)
  314. {
  315. V_INAME(CMuteTrack::SetParam);
  316. V_PTR_WRITE(pData,1);
  317. V_REFGUID(rCommandGuid);
  318. if (rCommandGuid != GUID_MuteParam) return DMUS_E_TYPE_UNSUPPORTED;
  319. HRESULT hr = S_OK;
  320. DMUS_MUTE_PARAM* pDMUS_MUTE_PARAM = (DMUS_MUTE_PARAM*) pData;
  321. EnterCriticalSection( &m_CriticalSection );
  322. TListItem<MapSequence>* pSeqScan = m_MapSequenceList.GetHead();
  323. for (; pSeqScan; pSeqScan = pSeqScan->GetNext())
  324. {
  325. if (pSeqScan->GetItemValue().m_dwPChannel == pDMUS_MUTE_PARAM->dwPChannel) break;
  326. }
  327. // make a new mapping
  328. TListItem<MuteMapping>* pNew = new TListItem<MuteMapping>;
  329. if (pNew)
  330. {
  331. MuteMapping& rNew = pNew->GetItemValue();
  332. rNew.m_mtTime = mtTime;
  333. rNew.m_dwPChannelMap = pDMUS_MUTE_PARAM->dwPChannelMap;
  334. rNew.m_fMute = pDMUS_MUTE_PARAM->fMute;
  335. if (pSeqScan)
  336. {
  337. // add the mapping to the current list
  338. pSeqScan->GetItemValue().m_Mappings.AddTail(pNew);
  339. }
  340. else
  341. {
  342. // make a list containing the mapping, and add it to the sequence list
  343. TListItem<MapSequence>* pNewSeq = new TListItem<MapSequence>;
  344. if (pNewSeq)
  345. {
  346. MapSequence& rNewSeq = pNewSeq->GetItemValue();
  347. rNewSeq.m_dwPChannel = pDMUS_MUTE_PARAM->dwPChannel;
  348. rNewSeq.m_Mappings.AddTail(pNew);
  349. m_MapSequenceList.AddTail(pNewSeq);
  350. }
  351. else
  352. {
  353. delete pNew;
  354. pNew = NULL;
  355. }
  356. }
  357. }
  358. if (!pNew)
  359. {
  360. hr = E_OUTOFMEMORY;
  361. }
  362. LeaveCriticalSection( &m_CriticalSection );
  363. return hr;
  364. }
  365. // IPersist methods
  366. HRESULT CMuteTrack::GetClassID( LPCLSID pClassID )
  367. {
  368. V_INAME(CMuteTrack::GetClassID);
  369. V_PTR_WRITE(pClassID, CLSID);
  370. *pClassID = CLSID_DirectMusicMuteTrack;
  371. return S_OK;
  372. }
  373. HRESULT CMuteTrack::IsParamSupported(
  374. /*[in]*/ REFGUID rGuid
  375. )
  376. {
  377. V_INAME(CMuteTrack::IsParamSupported);
  378. V_REFGUID(rGuid);
  379. return rGuid == GUID_MuteParam ? S_OK : DMUS_E_TYPE_UNSUPPORTED;
  380. }
  381. // IPersistStream methods
  382. HRESULT CMuteTrack::IsDirty()
  383. {
  384. return m_bRequiresSave ? S_OK : S_FALSE;
  385. }
  386. HRESULT CMuteTrack::Save( LPSTREAM pStream, BOOL fClearDirty )
  387. {
  388. V_INAME(CMuteTrack::Save);
  389. V_INTERFACE(pStream);
  390. IAARIFFStream* pRIFF ;
  391. MMCKINFO ck;
  392. HRESULT hr;
  393. DWORD cb;
  394. DWORD dwSize;
  395. DMUS_IO_MUTE oMute;
  396. TListItem<MapSequence>* pSeqScan = m_MapSequenceList.GetHead();
  397. EnterCriticalSection( &m_CriticalSection );
  398. hr = AllocRIFFStream( pStream, &pRIFF );
  399. if (!SUCCEEDED(hr))
  400. {
  401. goto ON_END;
  402. }
  403. hr = E_FAIL;
  404. ck.ckid = DMUS_FOURCC_MUTE_CHUNK;
  405. if( pRIFF->CreateChunk( &ck, 0 ) == 0 )
  406. {
  407. dwSize = sizeof( DMUS_IO_MUTE );
  408. hr = pStream->Write( &dwSize, sizeof( dwSize ), &cb );
  409. if( FAILED( hr ) || cb != sizeof( dwSize ) )
  410. {
  411. if (SUCCEEDED(hr)) hr = E_FAIL;
  412. goto ON_END;
  413. }
  414. for( ; pSeqScan; pSeqScan = pSeqScan->GetNext() )
  415. {
  416. MapSequence& rSeqScan = pSeqScan->GetItemValue();
  417. DWORD dwPChannel = rSeqScan.m_dwPChannel;
  418. TListItem<MuteMapping>* pScan = rSeqScan.m_Mappings.GetHead();
  419. for( ; pScan; pScan = pScan->GetNext() )
  420. {
  421. MuteMapping& rScan = pScan->GetItemValue();
  422. memset( &oMute, 0, sizeof( oMute ) );
  423. oMute.mtTime = rScan.m_mtTime;
  424. oMute.dwPChannel = dwPChannel;
  425. oMute.dwPChannelMap = rScan.m_fMute ? DMUS_PCHANNEL_MUTE : rScan.m_dwPChannelMap;
  426. if( FAILED( pStream->Write( &oMute, sizeof( oMute ), &cb ) ) ||
  427. cb != sizeof( oMute ) )
  428. {
  429. break;
  430. }
  431. }
  432. }
  433. if( pSeqScan == NULL &&
  434. pRIFF->Ascend( &ck, 0 ) == 0 )
  435. {
  436. hr = S_OK;
  437. }
  438. }
  439. ON_END:
  440. if (pRIFF) pRIFF->Release();
  441. LeaveCriticalSection( &m_CriticalSection );
  442. return hr;
  443. }
  444. HRESULT CMuteTrack::GetSizeMax( ULARGE_INTEGER* /*pcbSize*/ )
  445. {
  446. return E_NOTIMPL;
  447. }
  448. BOOL Less(MuteMapping& Mute1, MuteMapping& Mute2)
  449. { return Mute1.m_mtTime < Mute2.m_mtTime; }
  450. HRESULT CMuteTrack::Load(LPSTREAM pStream )
  451. {
  452. V_INAME(CMuteTrack::Load);
  453. V_INTERFACE(pStream);
  454. long lFileSize = 0;
  455. DWORD dwNodeSize;
  456. DWORD cb;
  457. MMCKINFO ck;
  458. IAARIFFStream* pRIFF;
  459. FOURCC id = 0;
  460. HRESULT hr = S_OK;
  461. DMUS_IO_MUTE iMute;
  462. DWORD dwPos;
  463. TListItem<MapSequence>* pSeqScan;
  464. EnterCriticalSection( &m_CriticalSection );
  465. Clear();
  466. dwPos = StreamTell( pStream );
  467. StreamSeek( pStream, dwPos, STREAM_SEEK_SET );
  468. if( SUCCEEDED( AllocRIFFStream( pStream, &pRIFF ) ) )
  469. {
  470. if (pRIFF->Descend( &ck, NULL, 0 ) == 0 &&
  471. ck.ckid == DMUS_FOURCC_MUTE_CHUNK)
  472. {
  473. lFileSize = ck.cksize;
  474. hr = pStream->Read( &dwNodeSize, sizeof( dwNodeSize ), &cb );
  475. if( SUCCEEDED( hr ) && cb == sizeof( dwNodeSize ) )
  476. {
  477. lFileSize -= 4; // for the size dword
  478. while( lFileSize > 0 )
  479. {
  480. // Once DMUS_IO_MUTE changes, add code here to handle the old struct
  481. if( dwNodeSize <= sizeof( DMUS_IO_MUTE ) )
  482. {
  483. pStream->Read( &iMute, dwNodeSize, NULL );
  484. }
  485. else
  486. {
  487. pStream->Read( &iMute, sizeof( DMUS_IO_MUTE ), NULL );
  488. StreamSeek( pStream, lFileSize - sizeof( DMUS_IO_MUTE ), STREAM_SEEK_CUR );
  489. }
  490. pSeqScan = m_MapSequenceList.GetHead();
  491. for (; pSeqScan; pSeqScan = pSeqScan->GetNext())
  492. {
  493. if (pSeqScan->GetItemValue().m_dwPChannel == iMute.dwPChannel) break;
  494. }
  495. // make a new mapping
  496. TListItem<MuteMapping>* pNew = new TListItem<MuteMapping>;
  497. if (pNew)
  498. {
  499. MuteMapping& rNew = pNew->GetItemValue();
  500. memset( &rNew, 0, sizeof( rNew ) );
  501. rNew.m_mtTime = iMute.mtTime;
  502. rNew.m_dwPChannelMap = iMute.dwPChannelMap;
  503. rNew.m_fMute = (iMute.dwPChannelMap == DMUS_PCHANNEL_MUTE) ? TRUE : FALSE;
  504. if (pSeqScan)
  505. {
  506. // add the mapping to the current list
  507. pSeqScan->GetItemValue().m_Mappings.AddTail(pNew);
  508. }
  509. else
  510. {
  511. // make a list containing the mapping, and add it to the sequence list
  512. TListItem<MapSequence>* pNewSeq = new TListItem<MapSequence>;
  513. if (pNewSeq)
  514. {
  515. MapSequence& rNewSeq = pNewSeq->GetItemValue();
  516. rNewSeq.m_dwPChannel = iMute.dwPChannel;
  517. rNewSeq.m_Mappings.AddTail(pNew);
  518. m_MapSequenceList.AddTail(pNewSeq);
  519. }
  520. else
  521. {
  522. delete pNew;
  523. pNew = NULL;
  524. }
  525. }
  526. }
  527. if (!pNew)
  528. {
  529. hr = E_OUTOFMEMORY;
  530. }
  531. lFileSize -= dwNodeSize;
  532. }
  533. }
  534. if( SUCCEEDED(hr) &&
  535. lFileSize == 0 &&
  536. pRIFF->Ascend( &ck, 0 ) == 0 )
  537. {
  538. pSeqScan = m_MapSequenceList.GetHead();
  539. for (; pSeqScan; pSeqScan = pSeqScan->GetNext())
  540. {
  541. pSeqScan->GetItemValue().m_Mappings.MergeSort(Less);
  542. }
  543. }
  544. else if (SUCCEEDED(hr)) hr = E_FAIL;
  545. }
  546. pRIFF->Release();
  547. }
  548. LeaveCriticalSection( &m_CriticalSection );
  549. return hr;
  550. }
  551. HRESULT STDMETHODCALLTYPE CMuteTrack::AddNotificationType(
  552. /* [in] */ REFGUID rGuidNotify)
  553. {
  554. return E_NOTIMPL;
  555. }
  556. HRESULT STDMETHODCALLTYPE CMuteTrack::RemoveNotificationType(
  557. /* [in] */ REFGUID rGuidNotify)
  558. {
  559. return E_NOTIMPL;
  560. }
  561. HRESULT STDMETHODCALLTYPE CMuteTrack::Clone(
  562. MUSIC_TIME mtStart,
  563. MUSIC_TIME mtEnd,
  564. IDirectMusicTrack** ppTrack)
  565. {
  566. V_INAME(CMuteTrack::Clone);
  567. V_PTRPTR_WRITE(ppTrack);
  568. HRESULT hr = S_OK;
  569. if(mtStart < 0 )
  570. {
  571. return E_INVALIDARG;
  572. }
  573. if(mtStart > mtEnd)
  574. {
  575. return E_INVALIDARG;
  576. }
  577. EnterCriticalSection( &m_CriticalSection );
  578. CMuteTrack *pDM;
  579. try
  580. {
  581. pDM = new CMuteTrack(*this, mtStart, mtEnd);
  582. }
  583. catch( ... )
  584. {
  585. pDM = NULL;
  586. }
  587. if (pDM == NULL) {
  588. LeaveCriticalSection( &m_CriticalSection );
  589. return E_OUTOFMEMORY;
  590. }
  591. hr = pDM->QueryInterface(IID_IDirectMusicTrack, (void**)ppTrack);
  592. pDM->Release();
  593. LeaveCriticalSection( &m_CriticalSection );
  594. return hr;
  595. }
  596. STDMETHODIMP CMuteTrack::GetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  597. REFERENCE_TIME* prtNext,void* pParam,void * pStateData, DWORD dwFlags)
  598. {
  599. HRESULT hr;
  600. MUSIC_TIME mtNext;
  601. if (dwFlags & DMUS_TRACK_PARAMF_CLOCK)
  602. {
  603. hr = GetParam(rguidType,(MUSIC_TIME) (rtTime / REF_PER_MIL), &mtNext, pParam);
  604. if (prtNext)
  605. {
  606. *prtNext = mtNext * REF_PER_MIL;
  607. }
  608. }
  609. else
  610. {
  611. hr = GetParam(rguidType,(MUSIC_TIME) rtTime, &mtNext, pParam);
  612. if (prtNext)
  613. {
  614. *prtNext = mtNext;
  615. }
  616. }
  617. return hr;
  618. }
  619. STDMETHODIMP CMuteTrack::SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  620. void* pParam, void * pStateData, DWORD dwFlags)
  621. {
  622. if (dwFlags & DMUS_TRACK_PARAMF_CLOCK)
  623. {
  624. rtTime /= REF_PER_MIL;
  625. }
  626. return SetParam(rguidType, (MUSIC_TIME) rtTime, pParam);
  627. }
  628. STDMETHODIMP CMuteTrack::PlayEx(void* pStateData,REFERENCE_TIME rtStart,
  629. REFERENCE_TIME rtEnd,REFERENCE_TIME rtOffset,
  630. DWORD dwFlags,IDirectMusicPerformance* pPerf,
  631. IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID)
  632. {
  633. V_INAME(IDirectMusicTrack::PlayEx);
  634. V_INTERFACE(pPerf);
  635. V_INTERFACE(pSegSt);
  636. EnterCriticalSection( &m_CriticalSection );
  637. // For now: do nothing.
  638. LeaveCriticalSection( &m_CriticalSection );
  639. return DMUS_S_END;
  640. }
  641. STDMETHODIMP CMuteTrack::Compose(
  642. IUnknown* pContext,
  643. DWORD dwTrackGroup,
  644. IDirectMusicTrack** ppResultTrack)
  645. {
  646. return E_NOTIMPL;
  647. }
  648. STDMETHODIMP CMuteTrack::Join(
  649. IDirectMusicTrack* pNewTrack,
  650. MUSIC_TIME mtJoin,
  651. IUnknown* pContext,
  652. DWORD dwTrackGroup,
  653. IDirectMusicTrack** ppResultTrack)
  654. {
  655. return E_NOTIMPL;
  656. }