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.

1538 lines
51 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1998-2001 Microsoft Corporation
  4. //
  5. // File: audtrk.cpp
  6. //
  7. //--------------------------------------------------------------------------
  8. // READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
  9. //
  10. // 4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX
  11. //
  12. // We disable this because we use exceptions and do *not* specify -GX (USE_NATIVE_EH in
  13. // sources).
  14. //
  15. // The one place we use exceptions is around construction of objects that call
  16. // InitializeCriticalSection. We guarantee that it is safe to use in this case with
  17. // the restriction given by not using -GX (automatic objects in the call chain between
  18. // throw and handler are not destructed). Turning on -GX buys us nothing but +10% to code
  19. // size because of the unwind code.
  20. //
  21. // Any other use of exceptions must follow these restrictions or -GX must be turned on.
  22. //
  23. // READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
  24. //
  25. #pragma warning(disable:4530)
  26. // AudTrk.cpp : Implementation of CAuditionTrack
  27. #include "AudTrk.h"
  28. #include "dmusici.h"
  29. #include "debug.h"
  30. #include "..\shared\Validate.h"
  31. //extern IStream* gpTempoStream;
  32. /////////////////////////////////////////////////////////////////////////////
  33. // AuditionTrackState
  34. AuditionTrackState::AuditionTrackState() :
  35. m_fTestVariations(TRUE), m_fByGUID(TRUE), m_bVariationLock(0), m_mtSectionOffset(0)
  36. {
  37. m_pPattern = NULL;
  38. memset(&m_guidPart, 0, sizeof(m_guidPart));
  39. }
  40. AuditionTrackState::~AuditionTrackState()
  41. {
  42. }
  43. BOOL AuditionTrackState::PlayAsIs()
  44. {
  45. return m_fTestVariations;
  46. }
  47. DWORD AuditionTrackState::Variations(DirectMusicPartRef& rPartRef, int nPartIndex)
  48. {
  49. if (m_bVariationLock && rPartRef.m_bVariationLockID == m_bVariationLock)
  50. {
  51. TraceI(4, "Variations for locked part\n");
  52. return m_dwVariation;
  53. }
  54. else if ( (m_fByGUID &&
  55. rPartRef.m_pDMPart &&
  56. rPartRef.m_dwLogicalPartID == m_dwPart &&
  57. rPartRef.m_pDMPart->m_guidPartID == m_guidPart) ||
  58. (!m_fByGUID && rPartRef.m_dwLogicalPartID == m_dwPart) )
  59. {
  60. TraceI(4, "Variations for current part\n");
  61. // return m_pdwVariationMask[wPart] & m_dwVariation;
  62. return m_dwVariation;
  63. }
  64. else
  65. {
  66. TraceI(4, "Variations for a different part\n");
  67. return (m_pVariations[nPartIndex] == 0xff) ? 0 : (1 << m_pVariations[nPartIndex]);
  68. }
  69. }
  70. HRESULT AuditionTrackState::InitVariationInfo(DWORD dwVariations, DWORD dwPart, REFGUID rGuidPart, BOOL fByGuid)
  71. {
  72. HRESULT hr = S_OK;
  73. m_dwVariation = dwVariations;
  74. m_dwPart = dwPart;
  75. m_guidPart = rGuidPart;
  76. m_fByGUID = fByGuid;
  77. if (!m_pPattern)
  78. {
  79. hr = DMUS_E_NOT_INIT;
  80. }
  81. else
  82. {
  83. if (rGuidPart == GUID_NULL)
  84. {
  85. m_bVariationLock = 0;
  86. }
  87. else
  88. {
  89. TListItem<DirectMusicPartRef>* pPartRef = m_pPattern->m_PartRefList.GetHead();
  90. for (short i = 0; pPartRef != NULL; pPartRef = pPartRef->GetNext(), i++)
  91. {
  92. DirectMusicPartRef& rPartRef = pPartRef->GetItemValue();
  93. if ((m_fByGUID && rPartRef.m_pDMPart && rPartRef.m_pDMPart->m_guidPartID == m_guidPart) ||
  94. (!m_fByGUID && rPartRef.m_dwLogicalPartID == m_dwPart) )
  95. {
  96. m_bVariationLock = rPartRef.m_bVariationLockID;
  97. }
  98. }
  99. }
  100. }
  101. return hr;
  102. }
  103. HRESULT AuditionTrackState::Play(
  104. MUSIC_TIME mtStart,
  105. MUSIC_TIME mtEnd,
  106. MUSIC_TIME mtOffset,
  107. REFERENCE_TIME rtOffset,
  108. IDirectMusicPerformance* pPerformance,
  109. DWORD dwFlags,
  110. BOOL fClockTime
  111. )
  112. {
  113. TraceI(4, "Play [%d:%d @ %d]\n", mtStart, mtEnd, mtOffset);
  114. m_mtPerformanceOffset = mtOffset;
  115. BOOL fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
  116. BOOL fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
  117. BOOL fLoop = (dwFlags & DMUS_TRACKF_LOOP) ? TRUE : FALSE;
  118. BOOL fControl = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
  119. if (fControl) // We need to make sure we get chords on beat boundaries
  120. {
  121. GetNextChord(mtStart, mtOffset, pPerformance, fStart);
  122. }
  123. MUSIC_TIME mtNotify = mtStart ? PatternTimeSig().CeilingBeat(mtStart) : 0;
  124. if( m_fStateActive && m_pPatternTrack->m_fNotifyMeasureBeat && !fClockTime &&
  125. ( mtNotify < mtEnd ) )
  126. {
  127. mtNotify = NotifyMeasureBeat( mtNotify, mtEnd, mtOffset, pPerformance, dwFlags );
  128. }
  129. bool fReLoop = false;
  130. MUSIC_TIME mtPatternLength = PatternTimeSig().ClocksPerMeasure() * m_pPattern->m_wNumMeasures;
  131. if ( (fLoop || fStart) && mtPatternLength )
  132. {
  133. m_mtSectionOffset = mtStart - (mtStart % mtPatternLength);
  134. }
  135. MUSIC_TIME mtLast = m_mtSectionOffset + mtPatternLength;
  136. MUSIC_TIME mtPartLast = min(mtEnd, mtLast);
  137. DWORD dwPartFlags = PLAYPARTSF_FIRST_CALL;
  138. if (fStart || fLoop || fSeek) dwPartFlags |= PLAYPARTSF_START;
  139. if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
  140. if ( fLoop || (mtStart > 0 && (fStart || fSeek || fControl)) ) dwPartFlags |= PLAYPARTSF_FLUSH;
  141. PlayParts(mtStart, mtPartLast, mtOffset, rtOffset, m_mtSectionOffset, pPerformance, dwPartFlags, dwFlags, fReLoop);
  142. if (fReLoop)
  143. {
  144. dwPartFlags = PLAYPARTSF_RELOOP;
  145. if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
  146. PlayParts(mtStart, mtPartLast, mtOffset, rtOffset, m_mtSectionOffset, pPerformance, dwPartFlags, dwFlags, fReLoop);
  147. }
  148. // If we need to reset the section offset, we do it after all the events in all the parts
  149. // have run. And then we need to run all events from pattern start to mtEnd.
  150. if (mtStart <= mtLast && mtLast < mtEnd)
  151. {
  152. m_mtSectionOffset = mtLast;
  153. InitPattern(m_pPattern, m_mtSectionOffset);
  154. dwPartFlags = 0;
  155. if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
  156. PlayParts(mtStart, mtEnd, mtOffset, rtOffset, m_mtSectionOffset, pPerformance, dwPartFlags, dwFlags, fReLoop);
  157. }
  158. if( m_fStateActive && m_pPatternTrack->m_fNotifyMeasureBeat && !fClockTime &&
  159. ( mtNotify < mtEnd ) )
  160. {
  161. NotifyMeasureBeat( mtNotify, mtEnd, mtOffset, pPerformance, dwFlags );
  162. }
  163. return S_OK;
  164. }
  165. /////////////////////////////////////////////////////////////////////////////
  166. // AuditionTrackInfo
  167. AuditionTrackInfo::AuditionTrackInfo() :
  168. m_pPattern(NULL), m_pdwVariations(NULL), m_dwVariations(0), m_dwPart(0), m_fByGUID(TRUE)
  169. {
  170. m_dwPatternTag = DMUS_PATTERN_AUDITION;
  171. memset(&m_guidPart, 0, sizeof(m_guidPart));
  172. }
  173. AuditionTrackInfo::~AuditionTrackInfo()
  174. {
  175. if (m_pPattern) m_pPattern->Release();
  176. if (m_pdwVariations) delete [] m_pdwVariations;
  177. }
  178. HRESULT AuditionTrackInfo::Init(
  179. /*[in]*/ IDirectMusicSegment* pSegment
  180. )
  181. {
  182. HRESULT hr = S_OK;
  183. return hr;
  184. }
  185. HRESULT AuditionTrackInfo::InitPlay(
  186. /*[in]*/ IDirectMusicTrack* pParentrack,
  187. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  188. /*[in]*/ IDirectMusicPerformance* pPerformance,
  189. /*[out]*/ void** ppStateData,
  190. /*[in]*/ DWORD dwTrackID,
  191. /*[in]*/ DWORD dwFlags
  192. )
  193. {
  194. if (!m_pPattern) return E_POINTER;
  195. IDirectMusicSegment* pSegment = NULL;
  196. AuditionTrackState* pStateData = new AuditionTrackState;
  197. if( NULL == pStateData )
  198. {
  199. return E_OUTOFMEMORY;
  200. }
  201. HRESULT hr = S_OK;
  202. // hr = InitTrackVariations();
  203. // if (FAILED(hr)) return hr;
  204. pStateData->m_dwValidate = m_dwValidate;
  205. *ppStateData = pStateData;
  206. StatePair SP(pSegmentState, pStateData);
  207. TListItem<StatePair>* pPair = new TListItem<StatePair>(SP);
  208. if (!pPair) return E_OUTOFMEMORY;
  209. m_StateList.AddHead(pPair);
  210. TListItem<StylePair>* pHead = m_pISList.GetHead();
  211. if (!pHead || !pHead->GetItemValue().m_pStyle) return E_FAIL;
  212. pHead->GetItemValue().m_pStyle->GetStyleInfo((void **)&pStateData->m_pStyle);
  213. pStateData->m_pTrack = pParentrack;
  214. pStateData->m_pPatternTrack = this;
  215. pStateData->m_dwVirtualTrackID = dwTrackID;
  216. pStateData->m_pPattern = NULL;
  217. pStateData->InitPattern(m_pPattern, 0);
  218. pStateData->InitVariationInfo(m_dwVariations, m_dwPart, m_guidPart, m_fByGUID);
  219. pStateData->m_pSegState = pSegmentState; // weak reference, no addref.
  220. pStateData->m_pPerformance = pPerformance; // weak reference, no addref.
  221. pStateData->m_mtPerformanceOffset = 0;
  222. pStateData->m_mtNextChordTime = 0;
  223. pStateData->m_mtCurrentChordTime = 0;
  224. hr = pStateData->ResetMappings();
  225. if (FAILED(hr)) return hr;
  226. if (m_fStateSetBySetParam)
  227. {
  228. pStateData->m_fStateActive = m_fActive;
  229. }
  230. else
  231. {
  232. pStateData->m_fStateActive = !(dwFlags & (DMUS_SEGF_CONTROL | DMUS_SEGF_SECONDARY));
  233. }
  234. if (m_lRandomNumberSeed)
  235. {
  236. pStateData->InitVariationSeeds(m_lRandomNumberSeed);
  237. }
  238. if( SUCCEEDED( pSegmentState->GetSegment(&pSegment)))
  239. {
  240. if (FAILED(pSegment->GetTrackGroup(pStateData->m_pTrack, &pStateData->m_dwGroupID)))
  241. {
  242. pStateData->m_dwGroupID = 0xffffffff;
  243. }
  244. pSegment->Release();
  245. }
  246. return S_OK;
  247. }
  248. HRESULT AuditionTrackInfo::InitTrackVariations()
  249. {
  250. // Do the PatternTrackInfo initialization
  251. PatternTrackInfo::InitTrackVariations(m_pPattern);
  252. // init the part's variation array
  253. if (m_pdwVariations)
  254. {
  255. delete [] m_pdwVariations;
  256. m_pdwVariations = NULL;
  257. }
  258. m_pdwVariations = new DWORD[m_pPattern->m_PartRefList.GetCount()];
  259. if (!m_pdwVariations) return E_OUTOFMEMORY;
  260. TListItem<DirectMusicPartRef>* pPartRef = m_pPattern->m_PartRefList.GetHead();
  261. for (short i = 0; pPartRef != NULL; pPartRef = pPartRef->GetNext(), i++)
  262. {
  263. DirectMusicPartRef& rPartRef = pPartRef->GetItemValue();
  264. m_pdwVariations[i] = 0;
  265. }
  266. return S_OK;
  267. }
  268. /////////////////////////////////////////////////////////////////////////////
  269. // CAuditionTrack
  270. CAuditionTrack::CAuditionTrack() :
  271. m_bRequiresSave(0), m_cRef(1), m_fCSInitialized(FALSE)
  272. {
  273. InterlockedIncrement(&g_cComponent);
  274. ::InitializeCriticalSection( &m_CriticalSection );
  275. m_fCSInitialized = TRUE;
  276. m_pTrackInfo = new AuditionTrackInfo;
  277. }
  278. CAuditionTrack::CAuditionTrack(
  279. const CAuditionTrack& rTrack, MUSIC_TIME mtStart, MUSIC_TIME mtEnd) :
  280. m_bRequiresSave(0), m_cRef(1), m_fCSInitialized(FALSE)
  281. {
  282. InterlockedIncrement(&g_cComponent);
  283. ::InitializeCriticalSection( &m_CriticalSection );
  284. m_fCSInitialized = TRUE;
  285. m_pTrackInfo = new AuditionTrackInfo((AuditionTrackInfo*)rTrack.m_pTrackInfo, mtStart, mtEnd);
  286. }
  287. CAuditionTrack::~CAuditionTrack()
  288. {
  289. if (m_pTrackInfo)
  290. {
  291. delete m_pTrackInfo;
  292. }
  293. if (m_fCSInitialized)
  294. {
  295. ::DeleteCriticalSection( &m_CriticalSection );
  296. }
  297. InterlockedDecrement(&g_cComponent);
  298. }
  299. STDMETHODIMP CAuditionTrack::QueryInterface(
  300. const IID &iid,
  301. void **ppv)
  302. {
  303. V_INAME(CAuditionTrack::QueryInterface);
  304. V_REFGUID(iid);
  305. V_PTRPTR_WRITE(ppv);
  306. if (iid == IID_IUnknown || iid == IID_IDirectMusicTrack || iid == IID_IDirectMusicTrack8)
  307. {
  308. *ppv = static_cast<IDirectMusicTrack*>(this);
  309. }
  310. else if (iid == IID_IPersistStream)
  311. {
  312. *ppv = static_cast<IPersistStream*>(this);
  313. }
  314. else if (iid == IID_IDirectMusicPatternTrack)
  315. {
  316. *ppv = static_cast<IDirectMusicPatternTrack*>(this);
  317. }
  318. else if (iid == IID_IAuditionTrack) // dx7 private interface
  319. {
  320. *ppv = static_cast<IAuditionTrack*>(this);
  321. }
  322. else if (iid == IID_IPrivatePatternTrack)
  323. {
  324. *ppv = static_cast<IPrivatePatternTrack*>(this);
  325. }
  326. else
  327. {
  328. *ppv = NULL;
  329. return E_NOINTERFACE;
  330. }
  331. reinterpret_cast<IUnknown*>(this)->AddRef();
  332. return S_OK;
  333. }
  334. STDMETHODIMP_(ULONG) CAuditionTrack::AddRef()
  335. {
  336. return InterlockedIncrement(&m_cRef);
  337. }
  338. STDMETHODIMP_(ULONG) CAuditionTrack::Release()
  339. {
  340. if (!InterlockedDecrement(&m_cRef))
  341. {
  342. delete this;
  343. return 0;
  344. }
  345. return m_cRef;
  346. }
  347. //////////////////////////////////////////////////////////////////////
  348. // IDirectMusicTrack::Init
  349. HRESULT CAuditionTrack::Init(
  350. /* [in] */ IDirectMusicSegment __RPC_FAR *pSegment)
  351. {
  352. V_INAME(CAuditionTrack::Init);
  353. V_INTERFACE(pSegment);
  354. HRESULT hr = S_OK;
  355. if (m_pTrackInfo == NULL)
  356. return DMUS_E_NOT_INIT;
  357. EnterCriticalSection( &m_CriticalSection );
  358. hr = m_pTrackInfo->MergePChannels();
  359. if (SUCCEEDED(hr))
  360. {
  361. pSegment->SetPChannelsUsed(m_pTrackInfo->m_dwPChannels, m_pTrackInfo->m_pdwPChannels);
  362. hr = m_pTrackInfo->Init(pSegment);
  363. }
  364. LeaveCriticalSection( &m_CriticalSection );
  365. return hr;
  366. }
  367. HRESULT CAuditionTrack::InitPlay(
  368. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  369. /*[in]*/ IDirectMusicPerformance* pPerformance,
  370. /*[out]*/ void** ppStateData,
  371. /*[in]*/ DWORD dwTrackID,
  372. /*[in]*/ DWORD dwFlags
  373. )
  374. {
  375. V_INAME(CAuditionTrack::InitPlay);
  376. V_PTRPTR_WRITE(ppStateData);
  377. V_INTERFACE(pSegmentState);
  378. V_INTERFACE(pPerformance);
  379. EnterCriticalSection( &m_CriticalSection );
  380. HRESULT hr = S_OK;
  381. if (m_pTrackInfo == NULL)
  382. {
  383. LeaveCriticalSection( &m_CriticalSection );
  384. return DMUS_E_NOT_INIT;
  385. }
  386. hr = m_pTrackInfo->InitPlay(this, pSegmentState, pPerformance, ppStateData, dwTrackID, dwFlags);
  387. LeaveCriticalSection( &m_CriticalSection );
  388. return hr;
  389. }
  390. HRESULT CAuditionTrack::EndPlay(
  391. /*[in]*/ void* pStateData
  392. )
  393. {
  394. V_INAME(CAuditionTrack::EndPlay);
  395. V_BUFPTR_WRITE(pStateData, sizeof(AuditionTrackState));
  396. HRESULT hr = DMUS_E_NOT_INIT;
  397. EnterCriticalSection( &m_CriticalSection );
  398. if (m_pTrackInfo)
  399. {
  400. hr = m_pTrackInfo->EndPlay((AuditionTrackState*)pStateData);
  401. }
  402. LeaveCriticalSection( &m_CriticalSection );
  403. return hr;
  404. }
  405. HRESULT CAuditionTrack::Play(
  406. /*[in]*/ void* pStateData,
  407. /*[in]*/ MUSIC_TIME mtStart,
  408. /*[in]*/ MUSIC_TIME mtEnd,
  409. /*[in]*/ MUSIC_TIME mtOffset,
  410. REFERENCE_TIME rtOffset,
  411. DWORD dwFlags,
  412. IDirectMusicPerformance* pPerf,
  413. IDirectMusicSegmentState* pSegState,
  414. DWORD dwVirtualID,
  415. BOOL fClockTime
  416. )
  417. {
  418. V_INAME(CAuditionTrack::Play);
  419. V_BUFPTR_WRITE( pStateData, sizeof(AuditionTrackState));
  420. V_INTERFACE(pPerf);
  421. V_INTERFACE(pSegState);
  422. HRESULT hr = DMUS_E_NOT_INIT;
  423. EnterCriticalSection( &m_CriticalSection );
  424. if (!m_pTrackInfo || m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION)
  425. {
  426. LeaveCriticalSection( &m_CriticalSection );
  427. return DMUS_E_NOT_INIT;
  428. }
  429. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  430. AuditionTrackState* pSD = (AuditionTrackState *)pStateData;
  431. if (pSD->m_dwValidate != m_pTrackInfo->m_dwValidate)
  432. {
  433. // new style inserted in track via Load. Resync state data.
  434. MUSIC_TIME mtNext = 0;
  435. pSD->m_pStyle = pSD->FindStyle(mtStart, mtNext);
  436. if (!pSD->m_pStyle)
  437. {
  438. hr = E_POINTER;
  439. }
  440. pSD->InitPattern(pTrackInfo->m_pPattern, 0);
  441. pSD->m_dwValidate = m_pTrackInfo->m_dwValidate;
  442. }
  443. if (pSD && pSD->m_pMappings)
  444. {
  445. BOOL fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
  446. BOOL fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
  447. BOOL fLoop = (dwFlags & DMUS_TRACKF_LOOP) ? TRUE : FALSE;
  448. BOOL fControl = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
  449. if (fStart || fSeek || fLoop || fControl)
  450. {
  451. if (pSD->m_fStateActive && !fClockTime) // if timesig events are enabled and using music time...
  452. {
  453. pSD->SendTimeSigMessage(mtStart, mtOffset, 0, pPerf);
  454. }
  455. pSD->m_fNewPattern = TRUE;
  456. pSD->m_mtCurrentChordTime = 0;
  457. pSD->m_mtNextChordTime = 0;
  458. pSD->m_mtLaterChordTime = 0;
  459. // pSD->m_CurrentChord.bSubChordCount = 0;
  460. for (DWORD dw = 0; dw < m_pTrackInfo->m_dwPChannels; dw++)
  461. {
  462. pSD->m_pMappings[dw].m_mtTime = 0;
  463. pSD->m_pMappings[dw].m_dwPChannelMap = m_pTrackInfo->m_pdwPChannels[dw];
  464. pSD->m_pMappings[dw].m_fMute = FALSE;
  465. }
  466. }
  467. hr = pSD->Play(mtStart, mtEnd, mtOffset, rtOffset, pPerf, dwFlags, fClockTime);
  468. }
  469. LeaveCriticalSection( &m_CriticalSection );
  470. return hr;
  471. }
  472. HRESULT CAuditionTrack::GetPriority(
  473. /*[out]*/ DWORD* pPriority
  474. )
  475. {
  476. return E_NOTIMPL;
  477. }
  478. HRESULT CAuditionTrack::GetParam(
  479. REFGUID rCommandGuid,
  480. MUSIC_TIME mtTime,
  481. void * pStateData,
  482. MUSIC_TIME* pmtNext,
  483. void *pData)
  484. {
  485. V_INAME(CAuditionTrack::GetParam);
  486. V_PTR_WRITE_OPT(pmtNext,MUSIC_TIME);
  487. V_PTR_WRITE(pData,1);
  488. V_PTR_WRITE_OPT(pStateData,1);
  489. V_REFGUID(rCommandGuid);
  490. EnterCriticalSection( &m_CriticalSection );
  491. HRESULT hr = S_OK;
  492. if (!m_pTrackInfo)
  493. {
  494. LeaveCriticalSection( &m_CriticalSection );
  495. return DMUS_E_NOT_INIT;
  496. }
  497. if( GUID_Valid_Start_Time == rCommandGuid )
  498. {
  499. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION) hr = DMUS_E_NOT_INIT;
  500. else
  501. {
  502. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  503. if (!pTrackInfo->m_pPattern) hr = E_POINTER;
  504. else
  505. {
  506. DMUS_VALID_START_PARAM* pValidStartData = (DMUS_VALID_START_PARAM*)pData;
  507. TListItem<MUSIC_TIME>* pScan = pTrackInfo->m_pPattern->m_StartTimeList.GetHead();
  508. for (; pScan; pScan = pScan->GetNext())
  509. {
  510. if (pScan->GetItemValue() >= mtTime)
  511. {
  512. pValidStartData->mtTime = pScan->GetItemValue() - mtTime;
  513. break;
  514. }
  515. }
  516. if (!pScan) hr = DMUS_E_NOT_FOUND;
  517. else
  518. {
  519. if (pmtNext)
  520. {
  521. if (pScan = pScan->GetNext())
  522. {
  523. *pmtNext = pScan->GetItemValue() - mtTime;
  524. }
  525. else
  526. {
  527. *pmtNext = 0;
  528. }
  529. }
  530. hr = S_OK;
  531. }
  532. }
  533. }
  534. }
  535. else if ( GUID_Variations == rCommandGuid )
  536. {
  537. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION) hr = DMUS_E_NOT_INIT;
  538. else
  539. {
  540. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  541. if (!pTrackInfo->m_pPattern) hr = E_POINTER;
  542. else
  543. {
  544. if (pStateData)
  545. {
  546. AuditionTrackState* pSD = (AuditionTrackState*)pStateData;
  547. DMUS_VARIATIONS_PARAM* pParam = (DMUS_VARIATIONS_PARAM*)pData;
  548. if (!pSD->m_pPattern) hr = E_POINTER;
  549. else
  550. {
  551. pParam->dwPChannelsUsed = pSD->m_pPattern->m_PartRefList.GetCount();
  552. pParam->padwPChannels = pSD->m_pdwPChannels;
  553. TListItem<DirectMusicPartRef>* pPartRef = pTrackInfo->m_pPattern->m_PartRefList.GetHead();
  554. for (short i = 0; pPartRef != NULL; pPartRef = pPartRef->GetNext(), i++)
  555. {
  556. DirectMusicPartRef& rPartRef = pPartRef->GetItemValue();
  557. pTrackInfo->m_pdwVariations[i] = pSD->Variations(rPartRef, i);
  558. }
  559. pParam->padwVariations = pTrackInfo->m_pdwVariations;
  560. if (pmtNext)
  561. {
  562. DirectMusicTimeSig& TimeSig = pTrackInfo->m_pPattern->m_timeSig;
  563. MUSIC_TIME mtToNextChord = !pSD->m_mtNextChordTime ? 0 : pSD->m_mtNextChordTime - mtTime;
  564. MUSIC_TIME mtPatternClocks = pTrackInfo->m_pPattern->m_wNumMeasures * TimeSig.ClocksPerMeasure();
  565. if (!mtToNextChord || mtToNextChord > mtPatternClocks)
  566. {
  567. *pmtNext = mtPatternClocks;
  568. }
  569. else
  570. {
  571. *pmtNext = mtToNextChord;
  572. }
  573. }
  574. }
  575. }
  576. else
  577. {
  578. hr = E_POINTER;
  579. }
  580. }
  581. }
  582. }
  583. else if (rCommandGuid == GUID_IDirectMusicPatternStyle)
  584. {
  585. if (m_pTrackInfo)
  586. {
  587. TListItem<StylePair>* pScan = m_pTrackInfo->m_pISList.GetHead();
  588. if (pScan)
  589. {
  590. IDirectMusicStyle* pDMStyle = NULL;
  591. IDMStyle* pStyle = pScan->GetItemValue().m_pStyle;
  592. if (!pStyle)
  593. {
  594. hr = E_POINTER;
  595. }
  596. else
  597. {
  598. pStyle->QueryInterface(IID_IDirectMusicStyle, (void**)&pDMStyle);
  599. // Note: QI with no Release has the effect of an AddRef
  600. *(IDirectMusicStyle**)pData = pDMStyle;
  601. if (pmtNext)
  602. {
  603. *pmtNext = 0;
  604. }
  605. hr = S_OK;
  606. }
  607. }
  608. else hr = DMUS_E_NOT_FOUND;
  609. }
  610. else hr = DMUS_E_NOT_INIT;
  611. }
  612. else
  613. {
  614. hr = DMUS_E_GET_UNSUPPORTED;
  615. }
  616. LeaveCriticalSection( &m_CriticalSection );
  617. return hr;
  618. }
  619. HRESULT CAuditionTrack::SetParam(
  620. REFGUID rguid,
  621. MUSIC_TIME mtTime,
  622. void __RPC_FAR *pData)
  623. {
  624. V_INAME(CAuditionTrack::SetParam);
  625. V_PTR_WRITE_OPT(pData,1);
  626. V_REFGUID(rguid);
  627. EnterCriticalSection( &m_CriticalSection );
  628. if (!m_pTrackInfo)
  629. {
  630. LeaveCriticalSection( &m_CriticalSection );
  631. return DMUS_E_NOT_INIT;
  632. }
  633. HRESULT hr = DMUS_E_SET_UNSUPPORTED;
  634. if( rguid == GUID_EnableTimeSig )
  635. {
  636. if( m_pTrackInfo->m_fStateSetBySetParam && m_pTrackInfo->m_fActive )
  637. {
  638. hr = DMUS_E_TYPE_DISABLED;
  639. }
  640. else
  641. {
  642. m_pTrackInfo->m_fStateSetBySetParam = TRUE;
  643. m_pTrackInfo->m_fActive = TRUE;
  644. hr = S_OK;
  645. }
  646. }
  647. else if( rguid == GUID_DisableTimeSig )
  648. {
  649. if( m_pTrackInfo->m_fStateSetBySetParam && !m_pTrackInfo->m_fActive )
  650. {
  651. hr = DMUS_E_TYPE_DISABLED;
  652. }
  653. else
  654. {
  655. m_pTrackInfo->m_fStateSetBySetParam = TRUE;
  656. m_pTrackInfo->m_fActive = FALSE;
  657. hr = S_OK;
  658. }
  659. }
  660. else if ( rguid == GUID_SeedVariations )
  661. {
  662. if (pData)
  663. {
  664. m_pTrackInfo->m_lRandomNumberSeed = *((long*) pData);
  665. hr = S_OK;
  666. }
  667. else hr = E_POINTER;
  668. }
  669. LeaveCriticalSection( &m_CriticalSection );
  670. return hr;
  671. }
  672. // IPersist methods
  673. HRESULT CAuditionTrack::GetClassID( LPCLSID pClassID )
  674. {
  675. V_INAME(CAuditionTrack::GetClassID);
  676. V_PTR_WRITE(pClassID, CLSID);
  677. *pClassID = CLSID_DirectMusicAuditionTrack;
  678. return S_OK;
  679. }
  680. HRESULT CAuditionTrack::IsParamSupported(
  681. /*[in]*/ REFGUID rGuid
  682. )
  683. {
  684. V_INAME(CAuditionTrack::IsParamSupported);
  685. V_REFGUID(rGuid);
  686. if (!m_pTrackInfo)
  687. {
  688. return DMUS_E_NOT_INIT;
  689. }
  690. if ( rGuid == GUID_SeedVariations ||
  691. rGuid == GUID_Valid_Start_Time ||
  692. rGuid == GUID_Variations ||
  693. rGuid == GUID_IDirectMusicPatternStyle)
  694. {
  695. return S_OK;
  696. }
  697. else if (m_pTrackInfo->m_fStateSetBySetParam)
  698. {
  699. if( m_pTrackInfo->m_fActive )
  700. {
  701. if( rGuid == GUID_DisableTimeSig ) return S_OK;
  702. if( rGuid == GUID_EnableTimeSig ) return DMUS_E_TYPE_DISABLED;
  703. }
  704. else
  705. {
  706. if( rGuid == GUID_EnableTimeSig ) return S_OK;
  707. if( rGuid == GUID_DisableTimeSig ) return DMUS_E_TYPE_DISABLED;
  708. }
  709. }
  710. else
  711. {
  712. if(( rGuid == GUID_DisableTimeSig ) ||
  713. ( rGuid == GUID_EnableTimeSig ) )
  714. {
  715. return S_OK;
  716. }
  717. }
  718. return DMUS_E_TYPE_UNSUPPORTED;
  719. }
  720. // IPersistStream methods
  721. HRESULT CAuditionTrack::IsDirty()
  722. {
  723. return m_bRequiresSave ? S_OK : S_FALSE;
  724. }
  725. // Saves the track's pattern in single pattern format
  726. HRESULT CAuditionTrack::Save( LPSTREAM pStream, BOOL fClearDirty )
  727. {
  728. V_INAME(CAuditionTrack::Save);
  729. V_INTERFACE(pStream);
  730. IAARIFFStream* pRIFF = NULL;
  731. MMCKINFO ckRiff;
  732. MMCKINFO ckPattern;
  733. HRESULT hr = S_OK;
  734. AuditionTrackInfo* pTrackInfo = NULL;
  735. EnterCriticalSection( &m_CriticalSection );
  736. if (!m_pTrackInfo)
  737. {
  738. hr = DMUS_E_NOT_INIT;
  739. }
  740. else
  741. {
  742. pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  743. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION ||
  744. !pTrackInfo->m_pPattern)
  745. {
  746. hr = DMUS_E_NOT_INIT;
  747. }
  748. }
  749. if ( SUCCEEDED(hr) && SUCCEEDED(hr = AllocRIFFStream( pStream, &pRIFF )) )
  750. {
  751. ckRiff.fccType = DMUS_FOURCC_PATTERN_FORM;
  752. hr = pRIFF->CreateChunk(&ckRiff,MMIO_CREATERIFF);
  753. if (SUCCEEDED(hr))
  754. {
  755. ckPattern.fccType = DMUS_FOURCC_PATTERN_LIST;
  756. hr = pRIFF->CreateChunk( &ckPattern, MMIO_CREATELIST );
  757. if (SUCCEEDED(hr))
  758. {
  759. hr = pTrackInfo->m_pPattern->DM_SaveSinglePattern( pRIFF );
  760. if (SUCCEEDED(hr))
  761. {
  762. pRIFF->Ascend(&ckPattern, 0);
  763. pRIFF->Ascend(&ckRiff, 0);
  764. }
  765. }
  766. }
  767. pRIFF->Release();
  768. }
  769. LeaveCriticalSection( &m_CriticalSection );
  770. return hr;
  771. }
  772. HRESULT CAuditionTrack::GetSizeMax( ULARGE_INTEGER* /*pcbSize*/ )
  773. {
  774. return E_NOTIMPL;
  775. }
  776. HRESULT CAuditionTrack::Load(LPSTREAM pIStream )
  777. {
  778. DWORD dwPos;
  779. IAARIFFStream* pIRiffStream;
  780. MMCKINFO ckMain;
  781. HRESULT hr = E_FAIL;
  782. bool fAdded = false;
  783. if( pIStream == NULL )
  784. {
  785. return E_INVALIDARG;
  786. }
  787. EnterCriticalSection( &m_CriticalSection );
  788. if (!m_pTrackInfo)
  789. {
  790. LeaveCriticalSection( &m_CriticalSection );
  791. return DMUS_E_NOT_INIT;
  792. }
  793. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  794. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION)
  795. {
  796. LeaveCriticalSection( &m_CriticalSection );
  797. return DMUS_E_NOT_INIT;
  798. }
  799. pTrackInfo->m_pISList.CleanUp();
  800. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  801. if (!pNew)
  802. {
  803. LeaveCriticalSection( &m_CriticalSection );
  804. return E_OUTOFMEMORY;
  805. }
  806. dwPos = StreamTell( pIStream );
  807. if( SUCCEEDED( AllocRIFFStream( pIStream, &pIRiffStream ) ) )
  808. {
  809. ckMain.fccType = DMUS_FOURCC_PATTERN_FORM;
  810. if( pIRiffStream->Descend( &ckMain, NULL, MMIO_FINDRIFF ) == 0 )
  811. {
  812. IDMStyle* pINewStyle = NULL;
  813. hr = ::CoCreateInstance(
  814. CLSID_DirectMusicStyle,
  815. NULL,
  816. CLSCTX_INPROC,
  817. IID_IDMStyle,
  818. (void**)&pINewStyle
  819. );
  820. if (SUCCEEDED(hr))
  821. {
  822. DMStyleStruct* pNewStyle;
  823. pINewStyle->GetStyleInfo((void**)&pNewStyle);
  824. memset(pNewStyle, 0, sizeof(DMStyleStruct));
  825. hr = LoadPattern(pIRiffStream, &ckMain, pNewStyle);
  826. if (SUCCEEDED(hr))
  827. {
  828. pNew->GetItemValue().m_mtTime = 0;
  829. pNew->GetItemValue().m_pStyle = pINewStyle;
  830. pTrackInfo->m_pISList.AddTail(pNew);
  831. fAdded = true;
  832. }
  833. }
  834. }
  835. pIRiffStream->Release();
  836. pIRiffStream = NULL;
  837. }
  838. if (!fAdded) delete pNew;
  839. m_pTrackInfo->m_dwValidate++;
  840. hr = m_pTrackInfo->MergePChannels();
  841. LeaveCriticalSection( &m_CriticalSection );
  842. return hr;
  843. }
  844. HRESULT CAuditionTrack::LoadPattern(IAARIFFStream* pIRiffStream, MMCKINFO* pckMain, DMStyleStruct* pNewStyle)
  845. {
  846. IStream* pIStream;
  847. MMCKINFO ck;
  848. MMCKINFO ckList;
  849. DWORD dwByteCount;
  850. DWORD dwSize;
  851. DWORD dwPos;
  852. HRESULT hr = S_OK;
  853. pIStream = pIRiffStream->GetStream();
  854. if ( pIStream == NULL ) return E_FAIL;
  855. dwPos = StreamTell( pIStream );
  856. while( pIRiffStream->Descend( &ck, pckMain, 0 ) == 0 )
  857. {
  858. switch( ck.ckid )
  859. {
  860. case DMUS_FOURCC_STYLE_CHUNK:
  861. {
  862. DMUS_IO_STYLE iDMStyle;
  863. dwSize = min( ck.cksize, sizeof( DMUS_IO_STYLE ) );
  864. hr = pIStream->Read( &iDMStyle, dwSize, &dwByteCount );
  865. if( FAILED( hr )
  866. || dwByteCount != dwSize )
  867. {
  868. hr = E_FAIL;
  869. goto ON_ERROR;
  870. }
  871. pNewStyle->m_TimeSignature.m_bBeatsPerMeasure = iDMStyle.timeSig.bBeatsPerMeasure;
  872. pNewStyle->m_TimeSignature.m_bBeat = iDMStyle.timeSig.bBeat;
  873. pNewStyle->m_TimeSignature.m_wGridsPerBeat = iDMStyle.timeSig.wGridsPerBeat;
  874. pNewStyle->m_dblTempo = iDMStyle.dblTempo;
  875. break;
  876. }
  877. case FOURCC_RIFF:
  878. case FOURCC_LIST:
  879. switch( ck.fccType )
  880. {
  881. case DMUS_FOURCC_PATTERN_LIST:
  882. StreamSeek( pIStream, dwPos, STREAM_SEEK_SET );
  883. CDirectMusicPattern* pPattern =
  884. new CDirectMusicPattern( &pNewStyle->m_TimeSignature, FALSE );
  885. if( pPattern == NULL )
  886. {
  887. hr = E_OUTOFMEMORY ;
  888. goto ON_ERROR;
  889. }
  890. ckList.fccType = DMUS_FOURCC_PATTERN_LIST;
  891. // Allow this to succeed whether the pattern chunk is
  892. // in a RIFF chunk or a LIST chunk.
  893. if( (ck.ckid == FOURCC_LIST && pIRiffStream->Descend( &ckList, NULL, MMIO_FINDLIST ) != 0) ||
  894. (ck.ckid == FOURCC_RIFF && pIRiffStream->Descend( &ckList, NULL, MMIO_FINDRIFF ) != 0) )
  895. {
  896. hr = E_FAIL;
  897. pPattern->Release();
  898. goto ON_ERROR;
  899. }
  900. hr = pPattern->DM_LoadPattern( pIRiffStream, &ckList, pNewStyle );
  901. pIRiffStream->Ascend( &ckList, 0 );
  902. if( FAILED( hr ) )
  903. {
  904. pPattern->Release();
  905. goto ON_ERROR;
  906. }
  907. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  908. if (pTrackInfo->m_pPattern) pTrackInfo->m_pPattern->Release();
  909. pTrackInfo->m_pPattern = pPattern;
  910. pTrackInfo->InitTrackVariations();
  911. break;
  912. }
  913. break;
  914. }
  915. pIRiffStream->Ascend( &ck, 0 );
  916. dwPos = StreamTell( pIStream );
  917. }
  918. ON_ERROR:
  919. pIStream->Release();
  920. return hr;
  921. }
  922. // Creates a segment containing an audition track with a style based on pStyle.
  923. // Also creates a Tempo track, based on the pattern's tempo. Other tracks
  924. // (e.g. chord and band tracks) must be added to the segment separately.
  925. // NOTE: might want to consider having a MUSIC_TIME parm here, so I can select
  926. // a style.
  927. HRESULT CAuditionTrack::CreateSegment(
  928. IDirectMusicStyle* pStyle, IDirectMusicSegment** ppSegment)
  929. {
  930. V_INAME(IDirectMusicPatternTrack::CreateSegment);
  931. V_INTERFACE(pStyle);
  932. V_PTRPTR_WRITE(ppSegment);
  933. HRESULT hr = S_OK;
  934. EnterCriticalSection( &m_CriticalSection );
  935. if (!m_pTrackInfo)
  936. {
  937. LeaveCriticalSection( &m_CriticalSection );
  938. return DMUS_E_NOT_INIT;
  939. }
  940. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  941. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION)
  942. {
  943. LeaveCriticalSection( &m_CriticalSection );
  944. return DMUS_E_NOT_INIT;
  945. }
  946. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  947. if (!pNew)
  948. {
  949. LeaveCriticalSection( &m_CriticalSection );
  950. return E_OUTOFMEMORY;
  951. }
  952. // 1. Give the track a style based on the one passed in (but with no patterns)
  953. IDMStyle* pIS = NULL;
  954. hr = pStyle->QueryInterface(IID_IDMStyle, (void**)&pIS);
  955. if (SUCCEEDED(hr))
  956. {
  957. IDMStyle* pINewStyle = NULL;
  958. hr = ::CoCreateInstance(
  959. CLSID_DirectMusicStyle,
  960. NULL,
  961. CLSCTX_INPROC,
  962. IID_IDMStyle,
  963. (void**)&pINewStyle
  964. );
  965. if (SUCCEEDED(hr))
  966. {
  967. DMStyleStruct* pOldStyle;
  968. DMStyleStruct* pNewStyle;
  969. pIS->GetStyleInfo((void**)&pOldStyle);
  970. pINewStyle->GetStyleInfo((void**)&pNewStyle);
  971. pNewStyle->m_guid = pOldStyle->m_guid;
  972. pNewStyle->m_strCategory = pOldStyle->m_strCategory;
  973. pNewStyle->m_strName = pOldStyle->m_strName;
  974. pNewStyle->m_dwVersionMS = pOldStyle->m_dwVersionMS;
  975. pNewStyle->m_dwVersionLS = pOldStyle->m_dwVersionLS;
  976. pNewStyle->m_TimeSignature = pOldStyle->m_TimeSignature;
  977. pNewStyle->m_dblTempo = pOldStyle->m_dblTempo;
  978. // Don't worry about bands and personalities...
  979. pNewStyle->m_pDefaultBand = NULL;
  980. pNewStyle->m_pDefaultPers = NULL;
  981. pNew->GetItemValue().m_mtTime = 0;
  982. pNew->GetItemValue().m_pStyle = pINewStyle;
  983. TListItem<DWORD>* pScan = pOldStyle->m_PChannelList.GetHead();
  984. for (; pScan; pScan = pScan->GetNext() )
  985. {
  986. TListItem<DWORD>* pdwItem = new TListItem<DWORD>(pScan->GetItemValue());
  987. if (!pdwItem)
  988. {
  989. hr = E_OUTOFMEMORY;
  990. }
  991. else
  992. {
  993. pNewStyle->m_PChannelList.AddHead(pdwItem);
  994. }
  995. }
  996. if (SUCCEEDED(hr))
  997. {
  998. pTrackInfo->m_pISList.AddTail(pNew);
  999. // 2. Create a Tempo Track in which to store the tempo events
  1000. //////////////////////////////////////////////////////////
  1001. DMUS_TEMPO_PARAM tempo;
  1002. tempo.mtTime = 0;
  1003. tempo.dblTempo = (double) pNewStyle->m_dblTempo;
  1004. //////////////////////////////////////////////////////////
  1005. //IPersistStream* pIPSTrack;
  1006. IDirectMusicTrack* pDMTrack = NULL;
  1007. if( SUCCEEDED( CoCreateInstance( CLSID_DirectMusicTempoTrack,
  1008. NULL, CLSCTX_INPROC, IID_IDirectMusicTrack,
  1009. (void**)&pDMTrack )))
  1010. {
  1011. GUID Guid = GUID_TempoParam;
  1012. if (!SUCCEEDED(pDMTrack->SetParam(Guid, 0, &tempo)))
  1013. {
  1014. pDMTrack = NULL;
  1015. }
  1016. }
  1017. // 3. Create a segment.
  1018. IDirectMusicSegment *pISegment;
  1019. hr = ::CoCreateInstance(
  1020. CLSID_DirectMusicSegment,
  1021. NULL,
  1022. CLSCTX_INPROC,
  1023. IID_IDirectMusicSegment,
  1024. (void**)&pISegment
  1025. );
  1026. if (SUCCEEDED(hr) )
  1027. {
  1028. // 4. Initialize the segment appropriately.
  1029. DirectMusicTimeSig& TimeSig = pNewStyle->m_TimeSignature;
  1030. pISegment->SetLength(TimeSig.ClocksPerMeasure()); // default to a length of 1 measure
  1031. pISegment->SetDefaultResolution(0);
  1032. pISegment->InsertTrack(this, 1);
  1033. if (pDMTrack)
  1034. {
  1035. pISegment->InsertTrack( pDMTrack, 1 );
  1036. pDMTrack->Release();
  1037. }
  1038. hr = S_OK;
  1039. *ppSegment = pISegment;
  1040. }
  1041. }
  1042. }
  1043. pIS->Release();
  1044. }
  1045. LeaveCriticalSection( &m_CriticalSection );
  1046. return hr;
  1047. }
  1048. // Sets the pattern for a track, given a style, the name of a pattern
  1049. // within the style, and the pattern's type (regular pattern/motif/fragment).
  1050. HRESULT CAuditionTrack::SetPatternByName(IDirectMusicSegmentState* pSegState,
  1051. WCHAR* wszName,
  1052. IDirectMusicStyle* pStyle,
  1053. DWORD dwPatternType,
  1054. DWORD* pdwLength)
  1055. {
  1056. V_INAME(IDirectMusicPatternTrack::SetPatternByName);
  1057. V_INTERFACE_OPT(pSegState);
  1058. V_PTR_READ(wszName, 1);
  1059. V_INTERFACE(pStyle);
  1060. V_PTR_WRITE(pdwLength, DWORD);
  1061. HRESULT hr = S_OK;
  1062. IDMStyle* pDMStyle = NULL;
  1063. IStream* pStream = NULL;
  1064. hr = pStyle->QueryInterface(IID_IDMStyle, (void**) &pDMStyle);
  1065. if (SUCCEEDED(hr))
  1066. {
  1067. hr = pDMStyle->GetPatternStream(wszName, dwPatternType, &pStream);
  1068. if (S_OK == hr)
  1069. {
  1070. hr = SetPattern(pSegState, pStream, pdwLength);
  1071. pStream->Release();
  1072. }
  1073. else
  1074. {
  1075. hr = DMUS_E_NOT_FOUND;
  1076. }
  1077. pDMStyle->Release();
  1078. }
  1079. return hr;
  1080. }
  1081. // Sets the pattern for a track. The pattern is read from pStream.
  1082. // IMPORTANT: Calling SetPattern could change the pattern's PartRef guid, which would make
  1083. // Variations cease to work. therefore, it's a good idea to call SetVariation after
  1084. // caling SetPattern.
  1085. HRESULT CAuditionTrack::SetPattern(IDirectMusicSegmentState* pSegState, IStream* pStream, DWORD* pdwLength)
  1086. {
  1087. IAARIFFStream* pIRiffStream;
  1088. MMCKINFO ckMain;
  1089. HRESULT hr = DMUS_E_NOT_INIT;
  1090. CDirectMusicPattern* pOldPattern = NULL;
  1091. EnterCriticalSection( &m_CriticalSection );
  1092. if (!m_pTrackInfo)
  1093. {
  1094. hr = DMUS_E_NOT_INIT;
  1095. }
  1096. else
  1097. {
  1098. DMStyleStruct* pStyle = NULL;
  1099. IDMStyle* pIS = NULL;
  1100. TListItem<StylePair>* pStyleItem = NULL;
  1101. PatternTrackState* pPatternState = m_pTrackInfo->FindState(pSegState);
  1102. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  1103. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION)
  1104. {
  1105. goto ON_END;
  1106. }
  1107. pStyleItem = pTrackInfo->m_pISList.GetHead();
  1108. if (!pStyleItem)
  1109. {
  1110. goto ON_END;
  1111. }
  1112. pIS = pStyleItem->GetItemValue().m_pStyle;
  1113. if (!pIS) goto ON_END;
  1114. pIS->GetStyleInfo((void**)&pStyle);
  1115. // 1. Set up the track's pattern.
  1116. if (pTrackInfo->m_pPattern)
  1117. {
  1118. pOldPattern = pTrackInfo->m_pPattern;
  1119. }
  1120. pTrackInfo->m_pPattern = new CDirectMusicPattern( &pStyle->m_TimeSignature, FALSE );
  1121. if( pTrackInfo->m_pPattern == NULL )
  1122. {
  1123. hr = E_OUTOFMEMORY ;
  1124. goto ON_END;
  1125. }
  1126. // 2. Load the pattern in single Pattern format
  1127. StreamSeek(pStream, 0, STREAM_SEEK_SET);
  1128. if( SUCCEEDED( AllocRIFFStream( pStream, &pIRiffStream ) ) )
  1129. {
  1130. ckMain.fccType = DMUS_FOURCC_PATTERN_LIST;
  1131. if( pIRiffStream->Descend( &ckMain, NULL, MMIO_FINDRIFF ) == 0 )
  1132. {
  1133. hr = pTrackInfo->m_pPattern->DM_LoadPattern( pIRiffStream, &ckMain, pStyle );
  1134. if (SUCCEEDED(hr))
  1135. {
  1136. DirectMusicTimeSig& TimeSig =
  1137. pTrackInfo->m_pPattern->m_timeSig.m_bBeat == 0 ?
  1138. pStyle->m_TimeSignature :
  1139. pTrackInfo->m_pPattern->m_timeSig;
  1140. *pdwLength = pTrackInfo->m_pPattern->m_wNumMeasures * TimeSig.ClocksPerMeasure();
  1141. }
  1142. }
  1143. pIRiffStream->Release();
  1144. hr = pTrackInfo->InitTrackVariations();
  1145. // Set up the new pattern.
  1146. if (pPatternState)
  1147. {
  1148. pPatternState->InitPattern(pTrackInfo->m_pPattern, 0, pOldPattern);
  1149. }
  1150. if (SUCCEEDED(hr))
  1151. {
  1152. // merge PChannels
  1153. hr = m_pTrackInfo->MergePChannels();
  1154. }
  1155. }
  1156. }
  1157. ON_END:
  1158. if (pOldPattern) pOldPattern->Release();
  1159. LeaveCriticalSection( &m_CriticalSection );
  1160. return hr;
  1161. }
  1162. // Sets the variations to be played for a part. All other parts use the MOAW
  1163. // to determine which variation plays.
  1164. HRESULT CAuditionTrack::SetVariation(
  1165. IDirectMusicSegmentState* pSegState, DWORD dwVariationFlags, DWORD dwPart)
  1166. {
  1167. V_INAME(IDirectMusicPatternTrack::SetVariation);
  1168. V_INTERFACE_OPT(pSegState);
  1169. HRESULT hr = DMUS_E_NOT_INIT;
  1170. PatternTrackState* pPatternState = NULL;
  1171. EnterCriticalSection( &m_CriticalSection );
  1172. if (!m_pTrackInfo)
  1173. {
  1174. LeaveCriticalSection( &m_CriticalSection );
  1175. return DMUS_E_NOT_INIT;
  1176. }
  1177. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  1178. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION)
  1179. {
  1180. goto ON_END;
  1181. }
  1182. pTrackInfo->m_dwVariations = dwVariationFlags;
  1183. pTrackInfo->m_dwPart = dwPart;
  1184. pTrackInfo->m_fByGUID = FALSE;
  1185. pPatternState = m_pTrackInfo->FindState(pSegState);
  1186. if (pPatternState)
  1187. {
  1188. AuditionTrackState* pState = (AuditionTrackState*)pPatternState;
  1189. GUID guidPart;
  1190. memset(&guidPart, 0, sizeof(guidPart));
  1191. pState->InitVariationInfo(dwVariationFlags, dwPart, guidPart, FALSE);
  1192. }
  1193. hr = S_OK;
  1194. ON_END:
  1195. LeaveCriticalSection( &m_CriticalSection );
  1196. return hr;
  1197. }
  1198. // Sets the variations to be played for a part. All other parts use the MOAW
  1199. // to determine which variation plays.
  1200. HRESULT CAuditionTrack::SetVariationByGUID(
  1201. IDirectMusicSegmentState* pSegState, DWORD dwVariationFlags, REFGUID rguidPart, DWORD dwPChannel)
  1202. {
  1203. HRESULT hr = DMUS_E_NOT_INIT;
  1204. PatternTrackState* pPatternState = NULL;
  1205. EnterCriticalSection( &m_CriticalSection );
  1206. if (!m_pTrackInfo)
  1207. {
  1208. LeaveCriticalSection( &m_CriticalSection );
  1209. return DMUS_E_NOT_INIT;
  1210. }
  1211. AuditionTrackInfo* pTrackInfo = (AuditionTrackInfo*)m_pTrackInfo;
  1212. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_AUDITION)
  1213. {
  1214. goto ON_END;
  1215. }
  1216. pTrackInfo->m_dwVariations = dwVariationFlags;
  1217. pTrackInfo->m_guidPart = rguidPart;
  1218. pTrackInfo->m_dwPart = dwPChannel;
  1219. pTrackInfo->m_fByGUID = TRUE;
  1220. pPatternState = m_pTrackInfo->FindState(pSegState);
  1221. if (pPatternState)
  1222. {
  1223. AuditionTrackState* pState = (AuditionTrackState*)pPatternState;
  1224. pState->InitVariationInfo(dwVariationFlags, dwPChannel, rguidPart, TRUE);
  1225. }
  1226. hr = S_OK;
  1227. ON_END:
  1228. LeaveCriticalSection( &m_CriticalSection );
  1229. return hr;
  1230. }
  1231. HRESULT STDMETHODCALLTYPE CAuditionTrack::AddNotificationType(
  1232. /* [in] */ REFGUID rGuidNotify)
  1233. {
  1234. V_INAME(CAuditionTrack::AddNotificationType);
  1235. V_REFGUID(rGuidNotify);
  1236. HRESULT hr = S_OK;
  1237. EnterCriticalSection( &m_CriticalSection );
  1238. if (m_pTrackInfo)
  1239. hr = m_pTrackInfo->AddNotificationType(rGuidNotify);
  1240. else
  1241. hr = DMUS_E_NOT_INIT;
  1242. LeaveCriticalSection( &m_CriticalSection );
  1243. return hr;
  1244. }
  1245. HRESULT STDMETHODCALLTYPE CAuditionTrack::RemoveNotificationType(
  1246. /* [in] */ REFGUID rGuidNotify)
  1247. {
  1248. V_INAME(CAuditionTrack::RemoveNotificationType);
  1249. V_REFGUID(rGuidNotify);
  1250. HRESULT hr = S_OK;
  1251. EnterCriticalSection( &m_CriticalSection );
  1252. if (m_pTrackInfo)
  1253. hr = m_pTrackInfo->RemoveNotificationType(rGuidNotify);
  1254. else
  1255. hr = DMUS_E_NOT_INIT;
  1256. LeaveCriticalSection( &m_CriticalSection );
  1257. return hr;
  1258. }
  1259. HRESULT STDMETHODCALLTYPE CAuditionTrack::Clone(
  1260. MUSIC_TIME mtStart,
  1261. MUSIC_TIME mtEnd,
  1262. IDirectMusicTrack** ppTrack)
  1263. {
  1264. V_INAME(CAuditionTrack::Clone);
  1265. V_PTRPTR_WRITE(ppTrack);
  1266. HRESULT hr = S_OK;
  1267. if(mtStart < 0 )
  1268. {
  1269. return E_INVALIDARG;
  1270. }
  1271. if(mtStart > mtEnd)
  1272. {
  1273. return E_INVALIDARG;
  1274. }
  1275. EnterCriticalSection( &m_CriticalSection );
  1276. CAuditionTrack *pDM;
  1277. try
  1278. {
  1279. pDM = new CAuditionTrack(*this, mtStart, mtEnd);
  1280. }
  1281. catch( ... )
  1282. {
  1283. pDM = NULL;
  1284. }
  1285. if (pDM == NULL) {
  1286. LeaveCriticalSection( &m_CriticalSection );
  1287. return E_OUTOFMEMORY;
  1288. }
  1289. hr = pDM->QueryInterface(IID_IDirectMusicTrack, (void**)ppTrack);
  1290. pDM->Release();
  1291. LeaveCriticalSection( &m_CriticalSection );
  1292. return hr;
  1293. }
  1294. HRESULT CAuditionTrack::GetParam(
  1295. REFGUID rCommandGuid,
  1296. MUSIC_TIME mtTime,
  1297. MUSIC_TIME* pmtNext,
  1298. void *pData)
  1299. {
  1300. return GetParam(rCommandGuid, mtTime, NULL, pmtNext, pData);
  1301. }
  1302. STDMETHODIMP CAuditionTrack::GetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  1303. REFERENCE_TIME* prtNext,void* pParam,void * pStateData, DWORD dwFlags)
  1304. {
  1305. HRESULT hr;
  1306. MUSIC_TIME mtNext = 0;
  1307. if (dwFlags & DMUS_TRACK_PARAMF_CLOCK)
  1308. {
  1309. hr = GetParam(rguidType,(MUSIC_TIME) (rtTime / REF_PER_MIL), pStateData, &mtNext, pParam);
  1310. if (prtNext)
  1311. {
  1312. *prtNext = mtNext * REF_PER_MIL;
  1313. }
  1314. }
  1315. else
  1316. {
  1317. hr = GetParam(rguidType,(MUSIC_TIME) rtTime, pStateData, &mtNext, pParam);
  1318. if (prtNext)
  1319. {
  1320. *prtNext = mtNext;
  1321. }
  1322. }
  1323. return hr;
  1324. }
  1325. STDMETHODIMP CAuditionTrack::SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  1326. void* pParam, void * pStateData, DWORD dwFlags)
  1327. {
  1328. if (dwFlags & DMUS_TRACK_PARAMF_CLOCK)
  1329. {
  1330. rtTime /= REF_PER_MIL;
  1331. }
  1332. return SetParam(rguidType, (MUSIC_TIME) rtTime , pParam);
  1333. }
  1334. STDMETHODIMP CAuditionTrack::PlayEx(void* pStateData,REFERENCE_TIME rtStart,
  1335. REFERENCE_TIME rtEnd,REFERENCE_TIME rtOffset,
  1336. DWORD dwFlags,IDirectMusicPerformance* pPerf,
  1337. IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID)
  1338. {
  1339. V_INAME(IDirectMusicTrack::PlayEx);
  1340. V_INTERFACE(pPerf);
  1341. V_INTERFACE(pSegSt);
  1342. HRESULT hr;
  1343. EnterCriticalSection(&m_CriticalSection);
  1344. if (dwFlags & DMUS_TRACKF_CLOCK)
  1345. {
  1346. // Convert all reference times to millisecond times. Then, just use same MUSIC_TIME
  1347. // variables.
  1348. hr = Play(pStateData,(MUSIC_TIME)(rtStart / REF_PER_MIL),(MUSIC_TIME)(rtEnd / REF_PER_MIL),
  1349. (MUSIC_TIME)(rtOffset / REF_PER_MIL),rtOffset,dwFlags,pPerf,pSegSt,dwVirtualID,TRUE);
  1350. }
  1351. else
  1352. {
  1353. hr = Play(pStateData,(MUSIC_TIME)rtStart,(MUSIC_TIME)rtEnd,
  1354. (MUSIC_TIME)rtOffset,0,dwFlags,pPerf,pSegSt,dwVirtualID,FALSE);
  1355. }
  1356. LeaveCriticalSection(&m_CriticalSection);
  1357. return hr;
  1358. }
  1359. STDMETHODIMP CAuditionTrack::Play(
  1360. void *pStateData, // @parm State data pointer, from <om .InitPlay>.
  1361. MUSIC_TIME mtStart, // @parm The start time to play.
  1362. MUSIC_TIME mtEnd, // @parm The end time to play.
  1363. MUSIC_TIME mtOffset,// @parm The offset to add to all messages sent to
  1364. // <om IDirectMusicPerformance.SendPMsg>.
  1365. DWORD dwFlags, // @parm Flags that indicate the state of this call.
  1366. // See <t DMUS_TRACKF_FLAGS>. If dwFlags == 0, this is a
  1367. // normal Play call continuing playback from the previous
  1368. // Play call.
  1369. IDirectMusicPerformance* pPerf, // @parm The <i IDirectMusicPerformance>, used to
  1370. // call <om IDirectMusicPerformance.AllocPMsg>,
  1371. // <om IDirectMusicPerformance.SendPMsg>, etc.
  1372. IDirectMusicSegmentState* pSegSt, // @parm The <i IDirectMusicSegmentState> this
  1373. // track belongs to. QueryInterface() can be called on this to
  1374. // obtain the SegmentState's <i IDirectMusicGraph> in order to
  1375. // call <om IDirectMusicGraph.StampPMsg>, for instance.
  1376. DWORD dwVirtualID // @parm This track's virtual track id, which must be set
  1377. // on any <t DMUS_PMSG>'s m_dwVirtualTrackID member that
  1378. // will be queued to <om IDirectMusicPerformance.SendPMsg>.
  1379. )
  1380. {
  1381. V_INAME(IDirectMusicTrack::Play);
  1382. V_INTERFACE(pPerf);
  1383. V_INTERFACE(pSegSt);
  1384. EnterCriticalSection(&m_CriticalSection);
  1385. HRESULT hr = Play(pStateData,mtStart,mtEnd,mtOffset,0,dwFlags,pPerf,pSegSt,dwVirtualID,FALSE);
  1386. LeaveCriticalSection(&m_CriticalSection);
  1387. return hr;
  1388. }
  1389. STDMETHODIMP CAuditionTrack::Compose(
  1390. IUnknown* pContext,
  1391. DWORD dwTrackGroup,
  1392. IDirectMusicTrack** ppResultTrack)
  1393. {
  1394. return E_NOTIMPL;
  1395. }
  1396. STDMETHODIMP CAuditionTrack::Join(
  1397. IDirectMusicTrack* pNewTrack,
  1398. MUSIC_TIME mtJoin,
  1399. IUnknown* pContext,
  1400. DWORD dwTrackGroup,
  1401. IDirectMusicTrack** ppResultTrack)
  1402. {
  1403. return E_NOTIMPL;
  1404. }