Source code of Windows XP (NT5)
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.

814 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) 1998-1999 Microsoft Corporation
  6. //
  7. // File: motiftrk.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. // MotifTrk.cpp : Implementation of CMotifTrack
  29. //#include "stdafx.h"
  30. //#include "Section.h"
  31. #include "MotifTrk.h"
  32. #include <stdlib.h> // for random number generator
  33. #include <time.h> // to seed random number generator
  34. #include "debug.h"
  35. #include "dmusici.h"
  36. #include "debug.h"
  37. #include "..\shared\Validate.h"
  38. /////////////////////////////////////////////////////////////////////////////
  39. // MotifTrackState
  40. MotifTrackState::MotifTrackState() :
  41. m_mtMotifStart(0)
  42. {
  43. }
  44. MotifTrackState::~MotifTrackState()
  45. {
  46. }
  47. HRESULT MotifTrackState::Play(
  48. MUSIC_TIME mtStart,
  49. MUSIC_TIME mtEnd,
  50. MUSIC_TIME mtOffset,
  51. REFERENCE_TIME rtOffset,
  52. IDirectMusicPerformance* pPerformance,
  53. DWORD dwFlags,
  54. BOOL fClockTime
  55. )
  56. {
  57. m_mtPerformanceOffset = mtOffset;
  58. BOOL fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
  59. BOOL fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
  60. BOOL fLoop = (dwFlags & DMUS_TRACKF_LOOP) ? TRUE : FALSE;
  61. BOOL fControl = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
  62. if (fControl) // We need to make sure we get chords on beat boundaries
  63. {
  64. GetNextChord(mtStart, mtOffset, pPerformance, fStart);
  65. }
  66. MUSIC_TIME mtNotify = mtStart ? PatternTimeSig().CeilingBeat(mtStart) : 0;
  67. if( m_fStateActive && m_pPatternTrack->m_fNotifyMeasureBeat && !fClockTime &&
  68. ( mtNotify < mtEnd ) )
  69. {
  70. mtNotify = NotifyMeasureBeat( mtNotify, mtEnd, mtOffset, pPerformance, dwFlags );
  71. }
  72. bool fReLoop = false;
  73. DWORD dwPartFlags = PLAYPARTSF_FIRST_CALL;
  74. if (fStart || fLoop || fSeek) dwPartFlags |= PLAYPARTSF_START;
  75. if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
  76. if ( fLoop || (mtStart > 0 && (fStart || fSeek || fControl)) ) dwPartFlags |= PLAYPARTSF_FLUSH;
  77. PlayParts(mtStart, mtEnd, mtOffset, rtOffset, 0, pPerformance, dwPartFlags, dwFlags, fReLoop);
  78. if (fReLoop)
  79. {
  80. dwPartFlags = PLAYPARTSF_RELOOP;
  81. if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
  82. PlayParts(mtStart, mtEnd, mtOffset, rtOffset, 0, pPerformance, dwPartFlags, dwFlags, fReLoop);
  83. }
  84. if( m_fStateActive && m_pPatternTrack->m_fNotifyMeasureBeat && !fClockTime &&
  85. ( mtNotify < mtEnd ) )
  86. {
  87. NotifyMeasureBeat( mtNotify, mtEnd, mtOffset, pPerformance, dwFlags );
  88. }
  89. return S_OK;
  90. }
  91. /////////////////////////////////////////////////////////////////////////////
  92. // MotifTrackInfo
  93. MotifTrackInfo::MotifTrackInfo() :
  94. m_pPattern(NULL)
  95. {
  96. m_dwPatternTag = DMUS_PATTERN_MOTIF;
  97. }
  98. MotifTrackInfo::~MotifTrackInfo()
  99. {
  100. if (m_pPattern) m_pPattern->Release();
  101. }
  102. HRESULT MotifTrackInfo::Init(
  103. /*[in]*/ IDirectMusicSegment* pSegment
  104. )
  105. {
  106. HRESULT hr = S_OK;
  107. return hr;
  108. }
  109. HRESULT MotifTrackInfo::InitPlay(
  110. /*[in]*/ IDirectMusicTrack* pParentrack,
  111. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  112. /*[in]*/ IDirectMusicPerformance* pPerformance,
  113. /*[out]*/ void** ppStateData,
  114. /*[in]*/ DWORD dwTrackID,
  115. /*[in]*/ DWORD dwFlags
  116. )
  117. {
  118. IDirectMusicSegment* pSegment = NULL;
  119. MotifTrackState* pStateData = new MotifTrackState;
  120. if( NULL == pStateData )
  121. {
  122. return E_OUTOFMEMORY;
  123. }
  124. *ppStateData = pStateData;
  125. StatePair SP(pSegmentState, pStateData);
  126. TListItem<StatePair>* pPair = new TListItem<StatePair>(SP);
  127. if (!pPair) return E_OUTOFMEMORY;
  128. m_StateList.AddHead(pPair);
  129. TListItem<StylePair>* pHead = m_pISList.GetHead();
  130. if (!pHead || !pHead->GetItemValue().m_pStyle) return E_FAIL;
  131. pHead->GetItemValue().m_pStyle->GetStyleInfo((void **)&pStateData->m_pStyle);
  132. pStateData->m_pTrack = pParentrack;
  133. pStateData->m_pPatternTrack = this;
  134. pStateData->m_dwVirtualTrackID = dwTrackID;
  135. pStateData->m_pPattern = NULL;
  136. pStateData->InitPattern(m_pPattern, 0);
  137. pStateData->m_pSegState = pSegmentState; // weak reference, no addref.
  138. pStateData->m_pPerformance = pPerformance; // weak reference, no addref.
  139. pStateData->m_mtPerformanceOffset = 0;
  140. pStateData->m_mtCurrentChordTime = 0;
  141. pStateData->m_mtNextChordTime = 0;
  142. pStateData->m_mtMotifStart = 0;
  143. HRESULT hr = pStateData->ResetMappings();
  144. if (FAILED(hr)) return hr;
  145. if (m_fStateSetBySetParam)
  146. {
  147. pStateData->m_fStateActive = m_fActive;
  148. }
  149. else
  150. {
  151. pStateData->m_fStateActive = !(dwFlags & (DMUS_SEGF_CONTROL | DMUS_SEGF_SECONDARY));
  152. }
  153. if (m_lRandomNumberSeed)
  154. {
  155. pStateData->InitVariationSeeds(m_lRandomNumberSeed);
  156. }
  157. if( SUCCEEDED( pSegmentState->GetSegment(&pSegment)))
  158. {
  159. if (FAILED(pSegment->GetTrackGroup(pStateData->m_pTrack, &pStateData->m_dwGroupID)))
  160. {
  161. pStateData->m_dwGroupID = 0xffffffff;
  162. }
  163. pSegment->Release();
  164. }
  165. return S_OK;
  166. }
  167. /////////////////////////////////////////////////////////////////////////////
  168. // CMotifTrack
  169. CMotifTrack::CMotifTrack() :
  170. m_bRequiresSave(0), m_cRef(1), m_fCSInitialized(FALSE)
  171. {
  172. InterlockedIncrement(&g_cComponent);
  173. ::InitializeCriticalSection( &m_CriticalSection );
  174. m_fCSInitialized = TRUE;
  175. srand((unsigned int)time(NULL));
  176. m_pTrackInfo = new MotifTrackInfo;
  177. }
  178. CMotifTrack::CMotifTrack(const CMotifTrack& rTrack, MUSIC_TIME mtStart, MUSIC_TIME mtEnd) :
  179. m_bRequiresSave(0), m_cRef(1), m_fCSInitialized(FALSE)
  180. {
  181. InterlockedIncrement(&g_cComponent);
  182. ::InitializeCriticalSection( &m_CriticalSection );
  183. m_fCSInitialized = TRUE;
  184. srand((unsigned int)time(NULL));
  185. m_pTrackInfo = new MotifTrackInfo((MotifTrackInfo*)rTrack.m_pTrackInfo, mtStart, mtEnd);
  186. }
  187. CMotifTrack::~CMotifTrack()
  188. {
  189. if (m_pTrackInfo)
  190. {
  191. delete m_pTrackInfo;
  192. }
  193. if (m_fCSInitialized)
  194. {
  195. ::DeleteCriticalSection( &m_CriticalSection );
  196. }
  197. InterlockedDecrement(&g_cComponent);
  198. }
  199. STDMETHODIMP CMotifTrack::QueryInterface(
  200. const IID &iid,
  201. void **ppv)
  202. {
  203. V_INAME(CMotifTrack::QueryInterface);
  204. V_REFGUID(iid);
  205. V_PTRPTR_WRITE(ppv);
  206. if (iid == IID_IUnknown || iid == IID_IDirectMusicTrack || iid == IID_IDirectMusicTrack8)
  207. {
  208. *ppv = static_cast<IDirectMusicTrack*>(this);
  209. }
  210. else if (iid == IID_IPersistStream)
  211. {
  212. *ppv = static_cast<IPersistStream*>(this);
  213. }
  214. else if (iid == IID_IMotifTrack)
  215. {
  216. *ppv = static_cast<IMotifTrack*>(this);
  217. }
  218. else
  219. {
  220. *ppv = NULL;
  221. return E_NOINTERFACE;
  222. }
  223. reinterpret_cast<IUnknown*>(this)->AddRef();
  224. return S_OK;
  225. }
  226. STDMETHODIMP_(ULONG) CMotifTrack::AddRef()
  227. {
  228. return InterlockedIncrement(&m_cRef);
  229. }
  230. STDMETHODIMP_(ULONG) CMotifTrack::Release()
  231. {
  232. if (!InterlockedDecrement(&m_cRef))
  233. {
  234. delete this;
  235. return 0;
  236. }
  237. return m_cRef;
  238. }
  239. //////////////////////////////////////////////////////////////////////
  240. // IDirectMusicTrack::Init
  241. HRESULT CMotifTrack::Init(
  242. /* [in] */ IDirectMusicSegment __RPC_FAR *pSegment)
  243. {
  244. V_INAME(CMotifTrack::Init);
  245. V_INTERFACE(pSegment);
  246. HRESULT hr = S_OK;
  247. if (!m_pTrackInfo)
  248. return DMUS_E_NOT_INIT;
  249. EnterCriticalSection( &m_CriticalSection );
  250. hr = m_pTrackInfo->MergePChannels();
  251. if (SUCCEEDED(hr))
  252. {
  253. pSegment->SetPChannelsUsed(m_pTrackInfo->m_dwPChannels, m_pTrackInfo->m_pdwPChannels);
  254. hr = m_pTrackInfo->Init(pSegment);
  255. }
  256. LeaveCriticalSection( &m_CriticalSection );
  257. return hr;
  258. }
  259. HRESULT CMotifTrack::InitPlay(
  260. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  261. /*[in]*/ IDirectMusicPerformance* pPerformance,
  262. /*[out]*/ void** ppStateData,
  263. /*[in]*/ DWORD dwTrackID,
  264. /*[in]*/ DWORD dwFlags
  265. )
  266. {
  267. V_INAME(CMotifTrack::InitPlay);
  268. V_PTRPTR_WRITE(ppStateData);
  269. V_INTERFACE(pSegmentState);
  270. V_INTERFACE(pPerformance);
  271. EnterCriticalSection( &m_CriticalSection );
  272. HRESULT hr = S_OK;
  273. if (!m_pTrackInfo)
  274. {
  275. LeaveCriticalSection( &m_CriticalSection );
  276. return DMUS_E_NOT_INIT;
  277. }
  278. hr = m_pTrackInfo->InitPlay(this, pSegmentState, pPerformance, ppStateData, dwTrackID, dwFlags);
  279. LeaveCriticalSection( &m_CriticalSection );
  280. return hr;
  281. }
  282. HRESULT CMotifTrack::EndPlay(
  283. /*[in]*/ void* pStateData
  284. )
  285. {
  286. V_INAME(CMotifTrack::EndPlay);
  287. V_BUFPTR_WRITE(pStateData, sizeof(MotifTrackState));
  288. HRESULT hr = DMUS_E_NOT_INIT;
  289. EnterCriticalSection( &m_CriticalSection );
  290. if (m_pTrackInfo)
  291. {
  292. hr = m_pTrackInfo->EndPlay((MotifTrackState*)pStateData);
  293. }
  294. LeaveCriticalSection( &m_CriticalSection );
  295. return hr;
  296. }
  297. HRESULT CMotifTrack::Play(
  298. /*[in]*/ void* pStateData,
  299. /*[in]*/ MUSIC_TIME mtStart,
  300. /*[in]*/ MUSIC_TIME mtEnd,
  301. /*[in]*/ MUSIC_TIME mtOffset,
  302. REFERENCE_TIME rtOffset,
  303. DWORD dwFlags,
  304. IDirectMusicPerformance* pPerf,
  305. IDirectMusicSegmentState* pSegState,
  306. DWORD dwVirtualID,
  307. BOOL fClockTime
  308. )
  309. {
  310. V_INAME(CMotifTrack::Play);
  311. V_BUFPTR_WRITE( pStateData, sizeof(MotifTrackState));
  312. V_INTERFACE(pPerf);
  313. V_INTERFACE(pSegState);
  314. HRESULT hr = DMUS_E_NOT_INIT;
  315. EnterCriticalSection( &m_CriticalSection );
  316. if (!m_pTrackInfo)
  317. {
  318. LeaveCriticalSection( &m_CriticalSection );
  319. return DMUS_E_NOT_INIT;
  320. }
  321. MotifTrackState* pSD = (MotifTrackState *)pStateData;
  322. if (pSD && pSD->m_pMappings)
  323. {
  324. BOOL fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
  325. BOOL fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
  326. BOOL fLoop = (dwFlags & DMUS_TRACKF_LOOP) ? TRUE : FALSE;
  327. BOOL fControl = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
  328. if (fStart || fSeek || fLoop || fControl)
  329. {
  330. pSD->m_fNewPattern = TRUE;
  331. pSD->m_mtCurrentChordTime = 0;
  332. pSD->m_mtNextChordTime = 0;
  333. pSD->m_mtLaterChordTime = 0;
  334. // pSD->m_CurrentChord.bSubChordCount = 0;
  335. for (DWORD dw = 0; dw < m_pTrackInfo->m_dwPChannels; dw++)
  336. {
  337. pSD->m_pMappings[dw].m_mtTime = 0;
  338. pSD->m_pMappings[dw].m_dwPChannelMap = m_pTrackInfo->m_pdwPChannels[dw];
  339. pSD->m_pMappings[dw].m_fMute = FALSE;
  340. }
  341. }
  342. hr = pSD->Play(mtStart, mtEnd, mtOffset, rtOffset, pPerf, dwFlags, fClockTime);
  343. }
  344. LeaveCriticalSection( &m_CriticalSection );
  345. return hr;
  346. }
  347. HRESULT CMotifTrack::GetPriority(
  348. /*[out]*/ DWORD* pPriority
  349. )
  350. {
  351. return E_NOTIMPL;
  352. }
  353. HRESULT CMotifTrack::GetParam(
  354. REFGUID rCommandGuid,
  355. MUSIC_TIME mtTime,
  356. MUSIC_TIME* pmtNext,
  357. void *pData)
  358. {
  359. V_INAME(CMotifTrack::GetParam);
  360. V_PTR_WRITE_OPT(pmtNext,MUSIC_TIME);
  361. V_PTR_WRITE(pData,1);
  362. V_REFGUID(rCommandGuid);
  363. EnterCriticalSection( &m_CriticalSection );
  364. if (!m_pTrackInfo)
  365. {
  366. LeaveCriticalSection( &m_CriticalSection );
  367. return DMUS_E_NOT_INIT;
  368. }
  369. HRESULT hr = S_OK;
  370. if( GUID_Valid_Start_Time == rCommandGuid )
  371. {
  372. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_MOTIF) hr = E_FAIL;
  373. else
  374. {
  375. MotifTrackInfo* pTrackInfo = (MotifTrackInfo*)m_pTrackInfo;
  376. if (!pTrackInfo->m_pPattern) hr = E_POINTER;
  377. else
  378. {
  379. DMUS_VALID_START_PARAM* pValidStartData = (DMUS_VALID_START_PARAM*)pData;
  380. TListItem<MUSIC_TIME>* pScan = pTrackInfo->m_pPattern->m_StartTimeList.GetHead();
  381. for (; pScan; pScan = pScan->GetNext())
  382. {
  383. if (pScan->GetItemValue() >= mtTime)
  384. {
  385. pValidStartData->mtTime = pScan->GetItemValue() - mtTime;
  386. break;
  387. }
  388. }
  389. if (!pScan) hr = DMUS_E_NOT_FOUND;
  390. else
  391. {
  392. if (pmtNext)
  393. {
  394. if (pScan = pScan->GetNext())
  395. {
  396. *pmtNext = pScan->GetItemValue() - mtTime;
  397. }
  398. else
  399. {
  400. *pmtNext = 0;
  401. }
  402. }
  403. hr = S_OK;
  404. }
  405. }
  406. }
  407. }
  408. else
  409. {
  410. hr = DMUS_E_GET_UNSUPPORTED;
  411. }
  412. LeaveCriticalSection( &m_CriticalSection );
  413. return hr;
  414. }
  415. HRESULT CMotifTrack::SetParam(
  416. REFGUID rguid,
  417. MUSIC_TIME mtTime,
  418. void __RPC_FAR *pData)
  419. {
  420. V_INAME(CMotifTrack::SetParam);
  421. V_PTR_WRITE_OPT(pData,1);
  422. V_REFGUID(rguid);
  423. EnterCriticalSection( &m_CriticalSection );
  424. if (!m_pTrackInfo)
  425. {
  426. LeaveCriticalSection( &m_CriticalSection );
  427. return DMUS_E_NOT_INIT;
  428. }
  429. HRESULT hr = DMUS_E_SET_UNSUPPORTED;
  430. if( rguid == GUID_EnableTimeSig )
  431. {
  432. if( m_pTrackInfo->m_fStateSetBySetParam && m_pTrackInfo->m_fActive )
  433. {
  434. hr = DMUS_E_TYPE_DISABLED;
  435. }
  436. else
  437. {
  438. m_pTrackInfo->m_fStateSetBySetParam = TRUE;
  439. m_pTrackInfo->m_fActive = TRUE;
  440. hr = S_OK;
  441. }
  442. }
  443. else if( rguid == GUID_DisableTimeSig )
  444. {
  445. if( m_pTrackInfo->m_fStateSetBySetParam && !m_pTrackInfo->m_fActive )
  446. {
  447. hr = DMUS_E_TYPE_DISABLED;
  448. }
  449. else
  450. {
  451. m_pTrackInfo->m_fStateSetBySetParam = TRUE;
  452. m_pTrackInfo->m_fActive = FALSE;
  453. hr = S_OK;
  454. }
  455. }
  456. else if ( rguid == GUID_SeedVariations )
  457. {
  458. if (pData)
  459. {
  460. m_pTrackInfo->m_lRandomNumberSeed = *((long*) pData);
  461. hr = S_OK;
  462. }
  463. else hr = E_POINTER;
  464. }
  465. LeaveCriticalSection( &m_CriticalSection );
  466. return hr;
  467. }
  468. // IPersist methods
  469. HRESULT CMotifTrack::GetClassID( LPCLSID pClassID )
  470. {
  471. V_INAME(CMotifTrack::GetClassID);
  472. V_PTR_WRITE(pClassID, CLSID);
  473. *pClassID = CLSID_DirectMusicMotifTrack;
  474. return S_OK;
  475. }
  476. HRESULT CMotifTrack::IsParamSupported(
  477. /*[in]*/ REFGUID rGuid
  478. )
  479. {
  480. V_INAME(CMotifTrack::IsParamSupported);
  481. V_REFGUID(rGuid);
  482. if (!m_pTrackInfo)
  483. {
  484. return DMUS_E_NOT_INIT;
  485. }
  486. if ( rGuid == GUID_SeedVariations || rGuid == GUID_Valid_Start_Time )
  487. {
  488. return S_OK;
  489. }
  490. else if (m_pTrackInfo->m_fStateSetBySetParam)
  491. {
  492. if( m_pTrackInfo->m_fActive )
  493. {
  494. if( rGuid == GUID_DisableTimeSig ) return S_OK;
  495. if( rGuid == GUID_EnableTimeSig ) return DMUS_E_TYPE_DISABLED;
  496. }
  497. else
  498. {
  499. if( rGuid == GUID_EnableTimeSig ) return S_OK;
  500. if( rGuid == GUID_DisableTimeSig ) return DMUS_E_TYPE_DISABLED;
  501. }
  502. }
  503. else
  504. {
  505. if(( rGuid == GUID_DisableTimeSig ) ||
  506. ( rGuid == GUID_EnableTimeSig ) )
  507. {
  508. return S_OK;
  509. }
  510. }
  511. return DMUS_E_TYPE_UNSUPPORTED;
  512. }
  513. // IPersistStream methods
  514. HRESULT CMotifTrack::IsDirty()
  515. {
  516. return m_bRequiresSave ? S_OK : S_FALSE;
  517. }
  518. HRESULT CMotifTrack::Save( LPSTREAM pStream, BOOL fClearDirty )
  519. {
  520. return E_NOTIMPL;
  521. }
  522. HRESULT CMotifTrack::GetSizeMax( ULARGE_INTEGER* /*pcbSize*/ )
  523. {
  524. return E_NOTIMPL;
  525. }
  526. HRESULT CMotifTrack::Load(LPSTREAM pStream )
  527. {
  528. return E_NOTIMPL;
  529. }
  530. HRESULT CMotifTrack::SetTrack(IUnknown* pStyle, void* pPattern)
  531. {
  532. if (!pStyle) return E_POINTER;
  533. HRESULT hr = E_FAIL;
  534. EnterCriticalSection( &m_CriticalSection );
  535. if (!m_pTrackInfo)
  536. {
  537. LeaveCriticalSection( &m_CriticalSection );
  538. return DMUS_E_NOT_INIT;
  539. }
  540. MotifTrackInfo* pTrackInfo = (MotifTrackInfo*)m_pTrackInfo;
  541. if (m_pTrackInfo->m_dwPatternTag == DMUS_PATTERN_MOTIF)
  542. {
  543. IDMStyle* pIS = NULL;
  544. hr = pStyle->QueryInterface(IID_IDMStyle, (void**)&pIS);
  545. if (SUCCEEDED(hr))
  546. {
  547. if (pTrackInfo->m_pPattern) pTrackInfo->m_pPattern->Release();
  548. pTrackInfo->m_pPattern = (CDirectMusicPattern*) pPattern;
  549. if (pTrackInfo->m_pPattern) pTrackInfo->m_pPattern->AddRef();
  550. pTrackInfo->InitTrackVariations(pTrackInfo->m_pPattern);
  551. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  552. if (!pNew) hr = E_OUTOFMEMORY;
  553. else
  554. {
  555. pNew->GetItemValue().m_mtTime = 0;
  556. pNew->GetItemValue().m_pStyle = pIS;
  557. pTrackInfo->m_pISList.AddTail(pNew);
  558. hr = S_OK;
  559. }
  560. pIS->Release();
  561. }
  562. }
  563. LeaveCriticalSection( &m_CriticalSection );
  564. return hr;
  565. }
  566. HRESULT STDMETHODCALLTYPE CMotifTrack::AddNotificationType(
  567. /* [in] */ REFGUID rGuidNotify)
  568. {
  569. V_INAME(CMotifTrack::AddNotificationType);
  570. V_REFGUID(rGuidNotify);
  571. HRESULT hr = S_OK;
  572. EnterCriticalSection( &m_CriticalSection );
  573. if (m_pTrackInfo)
  574. hr = m_pTrackInfo->AddNotificationType(rGuidNotify);
  575. else
  576. hr = DMUS_E_NOT_INIT;
  577. LeaveCriticalSection( &m_CriticalSection );
  578. return hr;
  579. }
  580. HRESULT STDMETHODCALLTYPE CMotifTrack::RemoveNotificationType(
  581. /* [in] */ REFGUID rGuidNotify)
  582. {
  583. V_INAME(CMotifTrack::RemoveNotificationType);
  584. V_REFGUID(rGuidNotify);
  585. HRESULT hr = S_OK;
  586. EnterCriticalSection( &m_CriticalSection );
  587. if (m_pTrackInfo)
  588. hr = m_pTrackInfo->RemoveNotificationType(rGuidNotify);
  589. else
  590. hr = DMUS_E_NOT_INIT;
  591. LeaveCriticalSection( &m_CriticalSection );
  592. return hr;
  593. }
  594. HRESULT STDMETHODCALLTYPE CMotifTrack::Clone(
  595. MUSIC_TIME mtStart,
  596. MUSIC_TIME mtEnd,
  597. IDirectMusicTrack** ppTrack)
  598. {
  599. V_INAME(CMotifTrack::Clone);
  600. V_PTRPTR_WRITE(ppTrack);
  601. HRESULT hr = S_OK;
  602. if(mtStart < 0 )
  603. {
  604. return E_INVALIDARG;
  605. }
  606. if(mtStart > mtEnd)
  607. {
  608. return E_INVALIDARG;
  609. }
  610. EnterCriticalSection( &m_CriticalSection );
  611. CMotifTrack *pDM;
  612. try
  613. {
  614. pDM = new CMotifTrack(*this, mtStart, mtEnd);
  615. }
  616. catch( ... )
  617. {
  618. pDM = NULL;
  619. }
  620. if (pDM == NULL) {
  621. LeaveCriticalSection( &m_CriticalSection );
  622. return E_OUTOFMEMORY;
  623. }
  624. hr = pDM->QueryInterface(IID_IDirectMusicTrack, (void**)ppTrack);
  625. pDM->Release();
  626. LeaveCriticalSection( &m_CriticalSection );
  627. return hr;
  628. }
  629. STDMETHODIMP CMotifTrack::GetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  630. REFERENCE_TIME* prtNext,void* pParam,void * pStateData, DWORD dwFlags)
  631. {
  632. HRESULT hr;
  633. MUSIC_TIME mtNext;
  634. if (dwFlags & DMUS_TRACK_PARAMF_CLOCK)
  635. {
  636. hr = GetParam(rguidType,(MUSIC_TIME) (rtTime / REF_PER_MIL), &mtNext, pParam);
  637. if (prtNext)
  638. {
  639. *prtNext = mtNext * REF_PER_MIL;
  640. }
  641. }
  642. else
  643. {
  644. hr = GetParam(rguidType,(MUSIC_TIME) rtTime, &mtNext, pParam);
  645. if (prtNext)
  646. {
  647. *prtNext = mtNext;
  648. }
  649. }
  650. return hr;
  651. }
  652. STDMETHODIMP CMotifTrack::SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  653. void* pParam, void * pStateData, DWORD dwFlags)
  654. {
  655. if (dwFlags & DMUS_TRACK_PARAMF_CLOCK)
  656. {
  657. rtTime /= REF_PER_MIL;
  658. }
  659. return SetParam(rguidType, (MUSIC_TIME) rtTime , pParam);
  660. }
  661. STDMETHODIMP CMotifTrack::PlayEx(void* pStateData,REFERENCE_TIME rtStart,
  662. REFERENCE_TIME rtEnd,REFERENCE_TIME rtOffset,
  663. DWORD dwFlags,IDirectMusicPerformance* pPerf,
  664. IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID)
  665. {
  666. V_INAME(IDirectMusicTrack::PlayEx);
  667. V_INTERFACE(pPerf);
  668. V_INTERFACE(pSegSt);
  669. HRESULT hr;
  670. EnterCriticalSection(&m_CriticalSection);
  671. if (dwFlags & DMUS_TRACKF_CLOCK)
  672. {
  673. // Convert all reference times to millisecond times. Then, just use same MUSIC_TIME
  674. // variables.
  675. hr = Play(pStateData,(MUSIC_TIME)(rtStart / REF_PER_MIL),(MUSIC_TIME)(rtEnd / REF_PER_MIL),
  676. (MUSIC_TIME)(rtOffset / REF_PER_MIL),rtOffset,dwFlags,pPerf,pSegSt,dwVirtualID,TRUE);
  677. }
  678. else
  679. {
  680. hr = Play(pStateData,(MUSIC_TIME)rtStart,(MUSIC_TIME)rtEnd,
  681. (MUSIC_TIME)rtOffset,0,dwFlags,pPerf,pSegSt,dwVirtualID,FALSE);
  682. }
  683. LeaveCriticalSection(&m_CriticalSection);
  684. return hr;
  685. }
  686. STDMETHODIMP CMotifTrack::Play(
  687. void *pStateData, // @parm State data pointer, from <om .InitPlay>.
  688. MUSIC_TIME mtStart, // @parm The start time to play.
  689. MUSIC_TIME mtEnd, // @parm The end time to play.
  690. MUSIC_TIME mtOffset,// @parm The offset to add to all messages sent to
  691. // <om IDirectMusicPerformance.SendPMsg>.
  692. DWORD dwFlags, // @parm Flags that indicate the state of this call.
  693. // See <t DMUS_TRACKF_FLAGS>. If dwFlags == 0, this is a
  694. // normal Play call continuing playback from the previous
  695. // Play call.
  696. IDirectMusicPerformance* pPerf, // @parm The <i IDirectMusicPerformance>, used to
  697. // call <om IDirectMusicPerformance.AllocPMsg>,
  698. // <om IDirectMusicPerformance.SendPMsg>, etc.
  699. IDirectMusicSegmentState* pSegSt, // @parm The <i IDirectMusicSegmentState> this
  700. // track belongs to. QueryInterface() can be called on this to
  701. // obtain the SegmentState's <i IDirectMusicGraph> in order to
  702. // call <om IDirectMusicGraph.StampPMsg>, for instance.
  703. DWORD dwVirtualID // @parm This track's virtual track id, which must be set
  704. // on any <t DMUS_PMSG>'s m_dwVirtualTrackID member that
  705. // will be queued to <om IDirectMusicPerformance.SendPMsg>.
  706. )
  707. {
  708. V_INAME(IDirectMusicTrack::Play);
  709. V_INTERFACE(pPerf);
  710. V_INTERFACE(pSegSt);
  711. EnterCriticalSection(&m_CriticalSection);
  712. HRESULT hr = Play(pStateData,mtStart,mtEnd,mtOffset,0,dwFlags,pPerf,pSegSt,dwVirtualID,FALSE);
  713. LeaveCriticalSection(&m_CriticalSection);
  714. return hr;
  715. }
  716. STDMETHODIMP CMotifTrack::Compose(
  717. IUnknown* pContext,
  718. DWORD dwTrackGroup,
  719. IDirectMusicTrack** ppResultTrack)
  720. {
  721. return E_NOTIMPL;
  722. }
  723. STDMETHODIMP CMotifTrack::Join(
  724. IDirectMusicTrack* pNewTrack,
  725. MUSIC_TIME mtJoin,
  726. IUnknown* pContext,
  727. DWORD dwTrackGroup,
  728. IDirectMusicTrack** ppResultTrack)
  729. {
  730. return E_NOTIMPL;
  731. }