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.

819 lines
24 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) 1998-1999 Microsoft Corporation
  6. //
  7. // File: perstrk.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. // PersTrk.cpp : Implementation of CPersonalityTrack
  29. #include "DMPers.h"
  30. #include "PersTrk.h"
  31. #include "dmusicc.h"
  32. #include "..\shared\Validate.h"
  33. /////////////////////////////////////////////////////////////////////////////
  34. // CPersonalityTrack
  35. CPersonalityTrack::CPersonalityTrack() :
  36. m_bRequiresSave(0),
  37. m_cRef(1),
  38. m_fCSInitialized(FALSE)
  39. {
  40. InterlockedIncrement(&g_cComponent);
  41. // Do this first since it might throw an exception
  42. //
  43. ::InitializeCriticalSection( &m_CriticalSection );
  44. m_fCSInitialized = TRUE;
  45. }
  46. CPersonalityTrack::CPersonalityTrack(const CPersonalityTrack& rTrack, MUSIC_TIME mtStart, MUSIC_TIME mtEnd) :
  47. m_bRequiresSave(0),
  48. m_cRef(1),
  49. m_fCSInitialized(FALSE)
  50. {
  51. InterlockedIncrement(&g_cComponent);
  52. // Do this first since it might throw an exception
  53. //
  54. ::InitializeCriticalSection( &m_CriticalSection );
  55. m_fCSInitialized = TRUE;
  56. TListItem<StampedPersonality>* pScan = rTrack.m_PersonalityList.GetHead();
  57. TListItem<StampedPersonality>* pPrevious = NULL;
  58. for(; pScan; pScan = pScan->GetNext())
  59. {
  60. StampedPersonality& rScan = pScan->GetItemValue();
  61. if (rScan.m_mtTime < mtStart)
  62. {
  63. pPrevious = pScan;
  64. }
  65. else if (rScan.m_mtTime < mtEnd)
  66. {
  67. if (rScan.m_mtTime == mtStart)
  68. {
  69. pPrevious = NULL;
  70. }
  71. TListItem<StampedPersonality>* pNew = new TListItem<StampedPersonality>;
  72. if (pNew)
  73. {
  74. StampedPersonality& rNew = pNew->GetItemValue();
  75. rNew.m_mtTime = rScan.m_mtTime - mtStart;
  76. rNew.m_pPersonality = rScan.m_pPersonality;
  77. if (rNew.m_pPersonality) rNew.m_pPersonality->AddRef();
  78. m_PersonalityList.AddTail(pNew);
  79. }
  80. }
  81. else break;
  82. }
  83. if (pPrevious)
  84. {
  85. TListItem<StampedPersonality>* pNew = new TListItem<StampedPersonality>;
  86. if (pNew)
  87. {
  88. StampedPersonality& rNew = pNew->GetItemValue();
  89. rNew.m_mtTime = 0;
  90. rNew.m_pPersonality = pPrevious->GetItemValue().m_pPersonality;
  91. if (rNew.m_pPersonality) rNew.m_pPersonality->AddRef();
  92. m_PersonalityList.AddHead(pNew);
  93. }
  94. }
  95. }
  96. CPersonalityTrack::~CPersonalityTrack()
  97. {
  98. if (m_fCSInitialized)
  99. {
  100. ::DeleteCriticalSection( &m_CriticalSection );
  101. }
  102. InterlockedDecrement(&g_cComponent);
  103. }
  104. STDMETHODIMP CPersonalityTrack::QueryInterface(
  105. const IID &iid,
  106. void **ppv)
  107. {
  108. V_INAME(CPersonalityTrack::QueryInterface);
  109. V_PTRPTR_WRITE(ppv);
  110. V_REFGUID(iid);
  111. if (iid == IID_IUnknown || iid == IID_IDirectMusicTrack || iid == IID_IDirectMusicTrack8)
  112. {
  113. *ppv = static_cast<IDirectMusicTrack*>(this);
  114. }
  115. else if (iid == IID_IPersistStream)
  116. {
  117. *ppv = static_cast<IPersistStream*>(this);
  118. }
  119. else
  120. {
  121. *ppv = NULL;
  122. return E_NOINTERFACE;
  123. }
  124. reinterpret_cast<IUnknown*>(this)->AddRef();
  125. return S_OK;
  126. }
  127. STDMETHODIMP_(ULONG) CPersonalityTrack::AddRef()
  128. {
  129. return InterlockedIncrement(&m_cRef);
  130. }
  131. STDMETHODIMP_(ULONG) CPersonalityTrack::Release()
  132. {
  133. if (!InterlockedDecrement(&m_cRef))
  134. {
  135. delete this;
  136. return 0;
  137. }
  138. return m_cRef;
  139. }
  140. HRESULT CPersonalityTrack::Init(
  141. /*[in]*/ IDirectMusicSegment* pSegment
  142. )
  143. {
  144. return S_OK;
  145. }
  146. HRESULT CPersonalityTrack::InitPlay(
  147. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  148. /*[in]*/ IDirectMusicPerformance* pPerformance,
  149. /*[out]*/ void** ppStateData,
  150. /*[in]*/ DWORD dwTrackID,
  151. /*[in]*/ DWORD dwFlags
  152. )
  153. {
  154. return S_OK;
  155. }
  156. HRESULT CPersonalityTrack::EndPlay(
  157. /*[in]*/ void* pStateData
  158. )
  159. {
  160. return S_OK;
  161. }
  162. HRESULT CPersonalityTrack::Play(
  163. /*[in]*/ void* pStateData,
  164. /*[in]*/ MUSIC_TIME mtStart,
  165. /*[in]*/ MUSIC_TIME mtEnd,
  166. /*[in]*/ MUSIC_TIME mtOffset,
  167. DWORD dwFlags,
  168. IDirectMusicPerformance* pPerf,
  169. IDirectMusicSegmentState* pSegState,
  170. DWORD dwVirtualID
  171. )
  172. {
  173. return S_OK;
  174. }
  175. HRESULT CPersonalityTrack::GetPriority(
  176. /*[out]*/ DWORD* pPriority
  177. )
  178. {
  179. return E_NOTIMPL;
  180. }
  181. HRESULT CPersonalityTrack::GetParam(
  182. REFGUID rCommandGuid,
  183. MUSIC_TIME mtTime,
  184. MUSIC_TIME* pmtNext,
  185. void* pData
  186. )
  187. {
  188. V_INAME(CPersonalityTrack::GetParam);
  189. V_PTR_WRITE_OPT(pmtNext,MUSIC_TIME);
  190. V_REFGUID(rCommandGuid);
  191. if( NULL == pData )
  192. {
  193. Trace(1, "ERROR: GetParam (chord map track): pParam is NULL.\n");
  194. return E_POINTER;
  195. }
  196. HRESULT hr;
  197. EnterCriticalSection(&m_CriticalSection);
  198. if (rCommandGuid == GUID_IDirectMusicChordMap)
  199. {
  200. TListItem<StampedPersonality>* pScan = m_PersonalityList.GetHead();
  201. if (pScan)
  202. {
  203. IDirectMusicChordMap* pPersonality = pScan->GetItemValue().m_pPersonality;
  204. for(pScan = pScan->GetNext(); pScan; pScan = pScan->GetNext())
  205. {
  206. StampedPersonality& rScan = pScan->GetItemValue();
  207. if (mtTime < rScan.m_mtTime && rScan.m_pPersonality) break; // ignore if NULL
  208. if (rScan.m_pPersonality) pPersonality = rScan.m_pPersonality; // skip if NULL
  209. }
  210. if (pPersonality)
  211. {
  212. pPersonality->AddRef();
  213. *(IDirectMusicChordMap**)pData = pPersonality;
  214. if (pmtNext)
  215. {
  216. *pmtNext = (pScan != NULL) ? pScan->GetItemValue().m_mtTime - mtTime : 0;
  217. }
  218. hr = S_OK;
  219. }
  220. else
  221. {
  222. Trace(1, "ERROR: GetParam (chord map track): Chord map list item is empty.\n");
  223. hr = E_POINTER;
  224. }
  225. }
  226. else
  227. {
  228. Trace(1, "ERROR: GetParam (chord map track): Chord map track is empty.\n");
  229. hr = DMUS_E_NOT_FOUND;
  230. }
  231. }
  232. else
  233. {
  234. Trace(1, "ERROR: GetParam (chord map track): Attempt to get an unsupported parameter.\n");
  235. hr = DMUS_E_GET_UNSUPPORTED;
  236. }
  237. LeaveCriticalSection(&m_CriticalSection);
  238. return hr;
  239. }
  240. HRESULT CPersonalityTrack::SetParam(
  241. REFGUID rCommandGuid,
  242. MUSIC_TIME mtTime,
  243. void __RPC_FAR *pData)
  244. {
  245. V_INAME(CPersonalityTrack::SetParam);
  246. V_REFGUID(rCommandGuid);
  247. HRESULT hr;
  248. if (!pData)
  249. {
  250. Trace(1, "ERROR: SetParam (chord map track): pParam is NULL.\n");
  251. return E_POINTER;
  252. }
  253. EnterCriticalSection( &m_CriticalSection );
  254. if (rCommandGuid == GUID_IDirectMusicChordMap)
  255. {
  256. IDirectMusicChordMap* pPers = (IDirectMusicChordMap*)pData;
  257. TListItem<StampedPersonality>* pPersItem = m_PersonalityList.GetHead();
  258. TListItem<StampedPersonality>* pPrevious = NULL;
  259. TListItem<StampedPersonality>* pNew = new TListItem<StampedPersonality>;
  260. if (!pNew)
  261. {
  262. hr = E_OUTOFMEMORY;
  263. }
  264. else
  265. {
  266. pNew->GetItemValue().m_mtTime = mtTime;
  267. pNew->GetItemValue().m_pPersonality = pPers;
  268. if (pPers) pPers->AddRef();
  269. for(; pPersItem != NULL; pPersItem = pPersItem->GetNext())
  270. {
  271. if (pPersItem->GetItemValue().m_mtTime >= mtTime) break;
  272. pPrevious = pPersItem;
  273. }
  274. if (pPrevious)
  275. {
  276. pPrevious->SetNext(pNew);
  277. pNew->SetNext(pPersItem);
  278. }
  279. else // pPersItem is current head of list
  280. {
  281. m_PersonalityList.AddHead(pNew);
  282. }
  283. if (pPersItem && pPersItem->GetItemValue().m_mtTime == mtTime)
  284. {
  285. // remove it
  286. if (pPersItem->GetItemValue().m_pPersonality)
  287. {
  288. pPersItem->GetItemValue().m_pPersonality->Release();
  289. }
  290. pPersItem->GetItemValue().m_pPersonality = NULL;
  291. pNew->SetNext(pPersItem->GetNext());
  292. pPersItem->SetNext(NULL);
  293. delete pPersItem;
  294. }
  295. hr = S_OK;
  296. }
  297. }
  298. else
  299. {
  300. Trace(1, "ERROR: SetParam (chord map track): Attempt to set an unsupported parameter.\n");
  301. hr = DMUS_E_SET_UNSUPPORTED;
  302. }
  303. LeaveCriticalSection( &m_CriticalSection );
  304. return hr;
  305. }
  306. // IPersist methods
  307. HRESULT CPersonalityTrack::GetClassID( LPCLSID pClassID )
  308. {
  309. V_INAME(CPersonalityTrack::GetClassID);
  310. V_PTR_WRITE(pClassID, CLSID);
  311. *pClassID = CLSID_DirectMusicChordMapTrack;
  312. return S_OK;
  313. }
  314. // IDirectMusicCommon Methods
  315. HRESULT CPersonalityTrack::GetName(
  316. /*[out]*/ BSTR* pbstrName
  317. )
  318. {
  319. return E_NOTIMPL;
  320. }
  321. HRESULT CPersonalityTrack::IsParamSupported(
  322. /*[in]*/ REFGUID rGuid
  323. )
  324. {
  325. V_INAME(CPersonalityTrack::IsParamSupported);
  326. V_REFGUID(rGuid);
  327. if (rGuid == GUID_IDirectMusicChordMap)
  328. return S_OK;
  329. else
  330. {
  331. Trace(2, "WARNING: IsParamSupported (chord map track): The parameter is not supported.\n");
  332. return DMUS_E_TYPE_UNSUPPORTED;
  333. }
  334. }
  335. // IPersistStream methods
  336. HRESULT CPersonalityTrack::IsDirty()
  337. {
  338. return m_bRequiresSave ? S_OK : S_FALSE;
  339. }
  340. HRESULT CPersonalityTrack::Save( LPSTREAM pStream, BOOL fClearDirty )
  341. {
  342. return E_NOTIMPL;
  343. }
  344. HRESULT CPersonalityTrack::GetSizeMax( ULARGE_INTEGER* /*pcbSize*/ )
  345. {
  346. return E_NOTIMPL;
  347. }
  348. BOOL Less(StampedPersonality& SP1, StampedPersonality& SP2)
  349. { return SP1.m_mtTime < SP2.m_mtTime; }
  350. HRESULT CPersonalityTrack::Load(LPSTREAM pStream )
  351. {
  352. V_INAME(CPersonalityTrack::Load);
  353. V_INTERFACE(pStream);
  354. IAARIFFStream* pIRiffStream;
  355. //MMCKINFO ckMain;
  356. MMCKINFO ck;
  357. HRESULT hr = E_FAIL;
  358. if ( pStream == NULL ) return E_INVALIDARG;
  359. EnterCriticalSection( &m_CriticalSection );
  360. if (m_PersonalityList.GetHead())
  361. {
  362. delete m_PersonalityList.GetHead();
  363. m_PersonalityList.RemoveAll();
  364. }
  365. if( SUCCEEDED( AllocRIFFStream( pStream, &pIRiffStream ) ) )
  366. {
  367. if (pIRiffStream->Descend( &ck, NULL, 0 ) == 0)
  368. {
  369. if (ck.ckid == FOURCC_LIST && ck.fccType == DMUS_FOURCC_PERS_TRACK_LIST)
  370. {
  371. hr = LoadPersRefList(pIRiffStream, &ck);
  372. }
  373. pIRiffStream->Ascend( &ck, 0 );
  374. }
  375. pIRiffStream->Release();
  376. }
  377. m_PersonalityList.MergeSort(Less);
  378. LeaveCriticalSection( &m_CriticalSection );
  379. return hr;
  380. }
  381. HRESULT CPersonalityTrack::LoadPersRefList( IAARIFFStream* pIRiffStream, MMCKINFO* pckParent )
  382. {
  383. HRESULT hr = S_OK;
  384. if (!pIRiffStream || !pckParent) return E_INVALIDARG;
  385. MMCKINFO ck;
  386. while ( pIRiffStream->Descend( &ck, pckParent, 0 ) == 0 )
  387. {
  388. if ( ck.ckid == FOURCC_LIST && ck.fccType == DMUS_FOURCC_PERS_REF_LIST )
  389. {
  390. hr = LoadPersRef(pIRiffStream, &ck);
  391. pIRiffStream->Ascend( &ck, 0 );
  392. }
  393. pIRiffStream->Ascend( &ck, 0 );
  394. }
  395. return hr;
  396. }
  397. HRESULT CPersonalityTrack::LoadPersRef( IAARIFFStream* pIRiffStream, MMCKINFO* pckParent )
  398. {
  399. HRESULT hr = S_OK;
  400. if (!pIRiffStream || !pckParent) return E_INVALIDARG;
  401. MMCKINFO ck;
  402. IStream* pIStream = pIRiffStream->GetStream();
  403. if(!pIStream) return E_FAIL;
  404. IDirectMusicChordMap* pPersonality = NULL;
  405. TListItem<StampedPersonality>* pNew = new TListItem<StampedPersonality>;
  406. if (!pNew) return E_OUTOFMEMORY;
  407. StampedPersonality& rNew = pNew->GetItemValue();
  408. while (pIRiffStream->Descend( &ck, pckParent, 0 ) == 0)
  409. {
  410. switch (ck.ckid)
  411. {
  412. case DMUS_FOURCC_TIME_STAMP_CHUNK:
  413. {
  414. DWORD dwTime;
  415. DWORD cb;
  416. hr = pIStream->Read( &dwTime, sizeof( dwTime ), &cb );
  417. if (FAILED(hr) || cb != sizeof( dwTime ) )
  418. {
  419. if (SUCCEEDED(hr)) hr = E_FAIL;
  420. pIRiffStream->Ascend( &ck, 0 );
  421. goto ON_END;
  422. }
  423. rNew.m_mtTime = dwTime;
  424. }
  425. break;
  426. case FOURCC_LIST:
  427. if (ck.fccType == DMUS_FOURCC_REF_LIST)
  428. {
  429. hr = LoadReference(pIStream, pIRiffStream, ck, &pPersonality);
  430. if (SUCCEEDED(hr))
  431. {
  432. rNew.m_pPersonality = pPersonality;
  433. }
  434. }
  435. break;
  436. }
  437. pIRiffStream->Ascend( &ck, 0 );
  438. }
  439. if (SUCCEEDED(hr))
  440. {
  441. m_PersonalityList.AddTail(pNew);
  442. }
  443. else
  444. {
  445. delete pNew;
  446. }
  447. ON_END:
  448. pIStream->Release();
  449. return hr;
  450. }
  451. //////////////////////////////////////////////////////////////////////
  452. // CPersonalityTrack::LoadReference
  453. HRESULT CPersonalityTrack::LoadReference(IStream *pStream,
  454. IAARIFFStream *pIRiffStream,
  455. MMCKINFO& ckParent,
  456. IDirectMusicChordMap** ppPersonality)
  457. {
  458. if (!pStream || !pIRiffStream || !ppPersonality) return E_INVALIDARG;
  459. IDirectMusicLoader* pLoader = NULL;
  460. IDirectMusicGetLoader *pIGetLoader;
  461. HRESULT hr = pStream->QueryInterface( IID_IDirectMusicGetLoader,(void **) &pIGetLoader );
  462. if (FAILED(hr)) return hr;
  463. hr = pIGetLoader->GetLoader(&pLoader);
  464. pIGetLoader->Release();
  465. if (FAILED(hr)) return hr;
  466. DMUS_OBJECTDESC desc;
  467. ZeroMemory(&desc, sizeof(desc));
  468. DWORD cbRead;
  469. MMCKINFO ckNext;
  470. ckNext.ckid = 0;
  471. ckNext.fccType = 0;
  472. DWORD dwSize = 0;
  473. while( pIRiffStream->Descend( &ckNext, &ckParent, 0 ) == 0 )
  474. {
  475. switch(ckNext.ckid)
  476. {
  477. case DMUS_FOURCC_REF_CHUNK:
  478. DMUS_IO_REFERENCE ioDMRef;
  479. hr = pStream->Read(&ioDMRef, sizeof(DMUS_IO_REFERENCE), &cbRead);
  480. if(SUCCEEDED(hr) && cbRead == sizeof(DMUS_IO_REFERENCE))
  481. {
  482. desc.guidClass = ioDMRef.guidClassID;
  483. desc.dwValidData |= ioDMRef.dwValidData;
  484. desc.dwValidData |= DMUS_OBJ_CLASS;
  485. }
  486. else if(SUCCEEDED(hr))
  487. {
  488. hr = E_FAIL;
  489. }
  490. break;
  491. case DMUS_FOURCC_GUID_CHUNK:
  492. hr = pStream->Read(&(desc.guidObject), sizeof(GUID), &cbRead);
  493. if(SUCCEEDED(hr) && cbRead == sizeof(GUID))
  494. {
  495. desc.dwValidData |= DMUS_OBJ_OBJECT;
  496. }
  497. else if(SUCCEEDED(hr))
  498. {
  499. hr = E_FAIL;
  500. }
  501. break;
  502. case DMUS_FOURCC_DATE_CHUNK:
  503. hr = pStream->Read(&(desc.ftDate), sizeof(FILETIME), &cbRead);
  504. if(SUCCEEDED(hr) && cbRead == sizeof(FILETIME))
  505. {
  506. desc.dwValidData |= DMUS_OBJ_DATE;
  507. }
  508. else if(SUCCEEDED(hr))
  509. {
  510. hr = E_FAIL;
  511. }
  512. break;
  513. case DMUS_FOURCC_NAME_CHUNK:
  514. dwSize = min(sizeof(desc.wszName), ckNext.cksize);
  515. hr = pStream->Read(desc.wszName, dwSize, &cbRead);
  516. if(SUCCEEDED(hr) && cbRead == dwSize)
  517. {
  518. desc.wszName[DMUS_MAX_NAME - 1] = L'\0';
  519. desc.dwValidData |= DMUS_OBJ_NAME;
  520. }
  521. else if(SUCCEEDED(hr))
  522. {
  523. hr = E_FAIL;
  524. }
  525. break;
  526. case DMUS_FOURCC_FILE_CHUNK:
  527. dwSize = min(sizeof(desc.wszFileName), ckNext.cksize);
  528. hr = pStream->Read(desc.wszFileName, dwSize, &cbRead);
  529. if(SUCCEEDED(hr) && cbRead == dwSize)
  530. {
  531. desc.wszFileName[DMUS_MAX_FILENAME - 1] = L'\0';
  532. desc.dwValidData |= DMUS_OBJ_FILENAME;
  533. }
  534. else if(SUCCEEDED(hr))
  535. {
  536. hr = E_FAIL;
  537. }
  538. break;
  539. case DMUS_FOURCC_CATEGORY_CHUNK:
  540. dwSize = min(sizeof(desc.wszCategory), ckNext.cksize);
  541. hr = pStream->Read(desc.wszCategory, dwSize, &cbRead);
  542. if(SUCCEEDED(hr) && cbRead == dwSize)
  543. {
  544. desc.wszCategory[DMUS_MAX_CATEGORY - 1] = L'\0';
  545. desc.dwValidData |= DMUS_OBJ_CATEGORY;
  546. }
  547. else if(SUCCEEDED(hr))
  548. {
  549. hr = E_FAIL;
  550. }
  551. break;
  552. case DMUS_FOURCC_VERSION_CHUNK:
  553. DMUS_IO_VERSION ioDMObjVer;
  554. hr = pStream->Read(&ioDMObjVer, sizeof(DMUS_IO_VERSION), &cbRead);
  555. if(SUCCEEDED(hr) && cbRead == sizeof(DMUS_IO_VERSION))
  556. {
  557. desc.vVersion.dwVersionMS = ioDMObjVer.dwVersionMS;
  558. desc.vVersion.dwVersionLS = ioDMObjVer.dwVersionLS;
  559. desc.dwValidData |= DMUS_OBJ_VERSION;
  560. }
  561. else if(SUCCEEDED(hr))
  562. {
  563. hr = E_FAIL;
  564. }
  565. break;
  566. default:
  567. break;
  568. }
  569. if(SUCCEEDED(hr) && pIRiffStream->Ascend(&ckNext, 0) == 0)
  570. {
  571. ckNext.ckid = 0;
  572. ckNext.fccType = 0;
  573. }
  574. else if (SUCCEEDED(hr)) hr = E_FAIL;
  575. }
  576. if(SUCCEEDED(hr))
  577. {
  578. desc.dwSize = sizeof(DMUS_OBJECTDESC);
  579. hr = pLoader->GetObject(&desc, IID_IDirectMusicChordMap, (void**)ppPersonality);
  580. }
  581. if (pLoader)
  582. {
  583. pLoader->Release();
  584. }
  585. return hr;
  586. }
  587. HRESULT STDMETHODCALLTYPE CPersonalityTrack::AddNotificationType(
  588. /* [in] */ REFGUID rGuidNotify)
  589. {
  590. return E_NOTIMPL;
  591. }
  592. HRESULT STDMETHODCALLTYPE CPersonalityTrack::RemoveNotificationType(
  593. /* [in] */ REFGUID rGuidNotify)
  594. {
  595. return E_NOTIMPL;
  596. }
  597. HRESULT STDMETHODCALLTYPE CPersonalityTrack::Clone(
  598. MUSIC_TIME mtStart,
  599. MUSIC_TIME mtEnd,
  600. IDirectMusicTrack** ppTrack)
  601. {
  602. V_INAME(CPersonalityTrack::Clone);
  603. V_PTRPTR_WRITE(ppTrack);
  604. HRESULT hr = S_OK;
  605. if(mtStart < 0 )
  606. {
  607. Trace(1, "ERROR: Clone (chord map track): Invalid start time.\n");
  608. return E_INVALIDARG;
  609. }
  610. if(mtStart > mtEnd)
  611. {
  612. Trace(1, "ERROR: Clone (chord map track): Invalid end time.\n");
  613. return E_INVALIDARG;
  614. }
  615. EnterCriticalSection( &m_CriticalSection );
  616. CPersonalityTrack *pDM;
  617. try
  618. {
  619. pDM = new CPersonalityTrack(*this, mtStart, mtEnd);
  620. }
  621. catch( ... )
  622. {
  623. pDM = NULL;
  624. }
  625. if (pDM == NULL) {
  626. LeaveCriticalSection( &m_CriticalSection );
  627. return E_OUTOFMEMORY;
  628. }
  629. hr = pDM->QueryInterface(IID_IDirectMusicTrack, (void**)ppTrack);
  630. pDM->Release();
  631. LeaveCriticalSection( &m_CriticalSection );
  632. return hr;
  633. }
  634. // IDirectMusicTrack8 Methods
  635. // For consistency with other track types
  636. STDMETHODIMP CPersonalityTrack::GetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  637. REFERENCE_TIME* prtNext,void* pParam,void * pStateData, DWORD dwFlags)
  638. {
  639. HRESULT hr;
  640. MUSIC_TIME mtNext;
  641. hr = GetParam(rguidType,(MUSIC_TIME) rtTime, &mtNext, pParam);
  642. if (prtNext)
  643. {
  644. *prtNext = mtNext;
  645. }
  646. return hr;
  647. }
  648. // For consistency with other track types
  649. STDMETHODIMP CPersonalityTrack::SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  650. void* pParam, void * pStateData, DWORD dwFlags)
  651. {
  652. return SetParam(rguidType, (MUSIC_TIME) rtTime , pParam);
  653. }
  654. // For consistency with other track types
  655. STDMETHODIMP CPersonalityTrack::PlayEx(void* pStateData,REFERENCE_TIME rtStart,
  656. REFERENCE_TIME rtEnd,REFERENCE_TIME rtOffset,
  657. DWORD dwFlags,IDirectMusicPerformance* pPerf,
  658. IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID)
  659. {
  660. V_INAME(IDirectMusicTrack::PlayEx);
  661. V_INTERFACE(pPerf);
  662. V_INTERFACE(pSegSt);
  663. HRESULT hr;
  664. EnterCriticalSection(&m_CriticalSection);
  665. hr = Play(pStateData, (MUSIC_TIME)rtStart, (MUSIC_TIME)rtEnd,
  666. (MUSIC_TIME)rtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
  667. LeaveCriticalSection(&m_CriticalSection);
  668. return hr;
  669. }
  670. STDMETHODIMP CPersonalityTrack::Compose(
  671. IUnknown* pContext,
  672. DWORD dwTrackGroup,
  673. IDirectMusicTrack** ppResultTrack)
  674. {
  675. return E_NOTIMPL;
  676. }
  677. STDMETHODIMP CPersonalityTrack::Join(
  678. IDirectMusicTrack* pNewTrack,
  679. MUSIC_TIME mtJoin,
  680. IUnknown* pContext,
  681. DWORD dwTrackGroup,
  682. IDirectMusicTrack** ppResultTrack)
  683. {
  684. V_INAME(IDirectMusicTrack::Join);
  685. V_INTERFACE(pNewTrack);
  686. V_INTERFACE_OPT(pContext);
  687. V_PTRPTR_WRITE_OPT(ppResultTrack);
  688. HRESULT hr = S_OK;
  689. EnterCriticalSection(&m_CriticalSection);
  690. if (ppResultTrack)
  691. {
  692. hr = Clone(0, mtJoin, ppResultTrack);
  693. if (SUCCEEDED(hr))
  694. {
  695. hr = ((CPersonalityTrack*)*ppResultTrack)->JoinInternal(pNewTrack, mtJoin, dwTrackGroup);
  696. }
  697. }
  698. else
  699. {
  700. hr = JoinInternal(pNewTrack, mtJoin, dwTrackGroup);
  701. }
  702. LeaveCriticalSection(&m_CriticalSection);
  703. return hr;
  704. }
  705. HRESULT CPersonalityTrack::JoinInternal(
  706. IDirectMusicTrack* pNewTrack,
  707. MUSIC_TIME mtJoin,
  708. DWORD dwTrackGroup)
  709. {
  710. HRESULT hr = S_OK;
  711. CPersonalityTrack* pOtherTrack = (CPersonalityTrack*)pNewTrack;
  712. TListItem<StampedPersonality>* pScan = pOtherTrack->m_PersonalityList.GetHead();
  713. for (; pScan; pScan = pScan->GetNext())
  714. {
  715. StampedPersonality& rScan = pScan->GetItemValue();
  716. TListItem<StampedPersonality>* pNew = new TListItem<StampedPersonality>;
  717. if (pNew)
  718. {
  719. StampedPersonality& rNew = pNew->GetItemValue();
  720. rNew.m_mtTime = rScan.m_mtTime + mtJoin;
  721. rNew.m_pPersonality = rScan.m_pPersonality;
  722. if (rNew.m_pPersonality) rNew.m_pPersonality->AddRef();
  723. m_PersonalityList.AddTail(pNew);
  724. }
  725. else
  726. {
  727. hr = E_OUTOFMEMORY;
  728. break;
  729. }
  730. }
  731. return hr;
  732. }