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.

1525 lines
50 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) 1998-1999 Microsoft Corporation
  6. //
  7. // File: styletrk.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. // StyleTrack.cpp : Implementation of CStyleTrack
  29. #include "StyleTrk.h"
  30. #include "dmusicc.h"
  31. #include <stdlib.h> // for random number generator
  32. #include <time.h> // to seed random number generator
  33. #include "debug.h"
  34. #include "debug.h"
  35. #include "..\shared\Validate.h"
  36. /////////////////////////////////////////////////////////////////////////////
  37. // StyleTrackState
  38. StyleTrackState::StyleTrackState() :
  39. m_mtSectionOffset(0), m_mtSectionOffsetTemp(0), m_mtOverlap(0),
  40. m_mtNextCommandTemp(0),
  41. m_mtNextCommandTime(0),
  42. m_mtNextStyleTime(0)
  43. {
  44. ZeroMemory(&m_CommandData , sizeof(m_CommandData));
  45. }
  46. StyleTrackState::~StyleTrackState()
  47. {
  48. m_PlayedPatterns.CleanUp();
  49. }
  50. HRESULT StyleTrackState::Play(
  51. MUSIC_TIME mtStart,
  52. MUSIC_TIME mtEnd,
  53. MUSIC_TIME mtOffset,
  54. REFERENCE_TIME rtOffset,
  55. IDirectMusicPerformance* pPerformance,
  56. DWORD dwFlags,
  57. BOOL fClockTime
  58. )
  59. {
  60. m_mtPerformanceOffset = mtOffset;
  61. BOOL fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
  62. BOOL fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
  63. BOOL fLoop = (dwFlags & DMUS_TRACKF_LOOP) ? TRUE : FALSE;
  64. BOOL fFlush = (dwFlags & DMUS_TRACKF_FLUSH) ? TRUE : FALSE;
  65. BOOL fDirty = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
  66. HRESULT hr = S_OK;
  67. TraceI(4, "Play [%d:%d @ %d]\n", mtStart, mtEnd, mtOffset);
  68. if (m_mtNextCommandTime == 0)
  69. {
  70. MUSIC_TIME mtBarLength = m_pStyle ? PatternTimeSig().ClocksPerMeasure() : 0;
  71. DMUS_COMMAND_PARAM_2 TempCommand;
  72. HRESULT hrCommand = E_FAIL;
  73. if (fDirty || fFlush)
  74. {
  75. char chGroove;
  76. HRESULT hrGroove = pPerformance->GetGlobalParam((GUID)GUID_PerfMasterGrooveLevel, &chGroove, 1);
  77. if (!SUCCEEDED(hrGroove)) chGroove = 0;
  78. BYTE bActualCommand = m_CommandData.bCommand;
  79. if (m_pStyle)
  80. {
  81. hrCommand = m_pStyle->GetCommand(mtStart, mtOffset, pPerformance, NULL, m_dwGroupID, &TempCommand, bActualCommand);
  82. }
  83. if (!fDirty && hrCommand == S_OK)
  84. {
  85. // Avoid getting a pattern that's the same as the current one.
  86. if (TempCommand.bGrooveLevel + chGroove == m_CommandData.bGrooveLevel &&
  87. bActualCommand == m_CommandData.bCommand)
  88. {
  89. hrCommand = E_FAIL;
  90. }
  91. }
  92. }
  93. MUSIC_TIME mtFirstCommand = 0;
  94. if (fStart || fLoop)
  95. {
  96. m_mtNextCommandTime = 0;
  97. }
  98. else
  99. {
  100. mtFirstCommand = mtStart;
  101. m_mtNextCommandTime = (mtBarLength) ? ((mtStart / mtBarLength) * mtBarLength) : 0;
  102. }
  103. if (fStart || fLoop || mtStart == 0 || hrCommand == S_OK || mtStart >= m_mtNextCommandTemp)
  104. {
  105. hr = GetNextPattern(dwFlags, mtFirstCommand, mtOffset, pPerformance, fLoop);
  106. if ( m_pPattern && mtStart > 0 && (fSeek || fDirty) )
  107. {
  108. while (SUCCEEDED(hr) && mtStart >= m_mtNextCommandTime)
  109. {
  110. hr = GetNextPattern(dwFlags, m_mtNextCommandTime, mtOffset, pPerformance, fLoop);
  111. }
  112. }
  113. fDirty = fDirty || fLoop; // make sure we get new variations if we skipped them above
  114. }
  115. else
  116. {
  117. m_mtNextCommandTime = m_mtNextCommandTemp;
  118. m_mtNextCommandTemp = 0;
  119. m_mtSectionOffset = m_mtSectionOffsetTemp;
  120. m_mtSectionOffsetTemp = 0;
  121. }
  122. }
  123. if (SUCCEEDED(hr))
  124. {
  125. if (fDirty) // We need to make sure we get chords on beat boundaries
  126. {
  127. GetNextChord(mtStart, mtOffset, pPerformance, fStart);
  128. }
  129. // for each part, play the events between start and end in the corresponding list
  130. // get new chords and commands when necessary
  131. MUSIC_TIME mtLast = m_mtNextCommandTime;
  132. bool fReLoop = false;
  133. MUSIC_TIME mtNotify = mtStart ? PatternTimeSig().CeilingBeat(mtStart) : 0;
  134. if( m_fStateActive && m_pPatternTrack->m_fNotifyMeasureBeat &&
  135. ( mtNotify < mtEnd ) )
  136. {
  137. mtNotify = NotifyMeasureBeat( mtNotify, mtEnd, mtOffset, pPerformance, dwFlags );
  138. }
  139. DWORD dwPartFlags = PLAYPARTSF_FIRST_CALL;
  140. if (fStart || fLoop || fSeek) dwPartFlags |= PLAYPARTSF_START;
  141. if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
  142. if ( fLoop || (mtStart > 0 && (fStart || fSeek || fDirty)) ) dwPartFlags |= PLAYPARTSF_FLUSH;
  143. MUSIC_TIME mtPartLast = min(mtEnd, mtLast);
  144. PlayParts(mtStart, mtPartLast, mtOffset, rtOffset, m_mtSectionOffset, pPerformance, dwPartFlags, dwFlags, fReLoop);
  145. // If we need to reloop any parts, do it
  146. if (fReLoop)
  147. {
  148. dwPartFlags = PLAYPARTSF_RELOOP;
  149. if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
  150. PlayParts(mtStart, mtPartLast, mtOffset, rtOffset, m_mtSectionOffset, pPerformance, dwPartFlags, dwFlags, fReLoop);
  151. }
  152. // If we need to get a new command, we do it after all the events in all the parts
  153. // have run. And then we need to run all events from command start to mtEnd.
  154. if (mtStart <= m_mtNextCommandTime && m_mtNextCommandTime < mtEnd)
  155. {
  156. hr = GetNextPattern(dwFlags & ~DMUS_TRACKF_START, m_mtNextCommandTime, mtOffset, pPerformance);
  157. if (SUCCEEDED(hr))
  158. {
  159. dwPartFlags = 0;
  160. if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
  161. PlayParts(mtStart, mtEnd, mtOffset, rtOffset, m_mtSectionOffset, pPerformance, dwPartFlags, dwFlags, fReLoop);
  162. }
  163. }
  164. if( SUCCEEDED(hr) &&
  165. m_fStateActive && m_pPatternTrack->m_fNotifyMeasureBeat &&
  166. ( mtNotify < mtEnd ) )
  167. {
  168. NotifyMeasureBeat( mtNotify, mtEnd, mtOffset, pPerformance, dwFlags );
  169. }
  170. }
  171. m_hrPlayCode = hr;
  172. return hr;
  173. }
  174. HRESULT StyleTrackState::GetNextPattern(DWORD dwFlags, MUSIC_TIME mtNow, MUSIC_TIME mtOffset, IDirectMusicPerformance* pPerformance, BOOL fSkipVariations)
  175. {
  176. bool fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
  177. bool fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
  178. bool fLoop = (dwFlags & DMUS_TRACKF_LOOP) ? TRUE : FALSE;
  179. bool fFlush = (dwFlags & DMUS_TRACKF_FLUSH) ? TRUE : FALSE;
  180. bool fDirty = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
  181. bool fNewMode = fStart || fDirty;
  182. // It doesn't seem to make sense to use anything other than the style's time signature
  183. // when looking for a new pattern.
  184. //TraceI(1, "New pattern at %d\n", mtNow);
  185. DMStyleStruct* pOldStyle = m_pStyle;
  186. if (m_mtNextStyleTime && mtNow >= m_mtNextStyleTime)
  187. {
  188. //TraceI(0, "New Style (%d) [%d]\n", m_mtNextStyleTime, mtNow);
  189. DMStyleStruct* pStyle = FindStyle(mtNow, m_mtNextStyleTime);
  190. if (!pStyle)
  191. {
  192. return E_POINTER;
  193. }
  194. else
  195. {
  196. m_pStyle = pStyle;
  197. fNewMode = true;
  198. }
  199. if (m_fStateActive) // if timesig events are enabled...
  200. {
  201. SendTimeSigMessage(mtNow, mtOffset, m_mtNextStyleTime, pPerformance);
  202. }
  203. }
  204. MUSIC_TIME mtOldMeasureTime = m_pPattern ? m_pPattern->TimeSignature(pOldStyle).ClocksPerMeasure() : m_pStyle->m_TimeSignature.ClocksPerMeasure();
  205. CDirectMusicPattern* pOldPattern = m_pPattern;
  206. CDirectMusicPattern* pTargetPattern = NULL;
  207. MUSIC_TIME mtMeasureTime = 0, mtNextCommand = 0;
  208. HRESULT hr = m_pStyle->GetPattern(fNewMode, mtNow, mtOffset, this, pPerformance, NULL, pTargetPattern, mtMeasureTime, mtNextCommand);
  209. if (SUCCEEDED(hr))
  210. {
  211. MUSIC_TIME mtSectionOffset = (!fDirty || m_mtSectionOffset || fLoop) ? m_mtSectionOffset : m_mtSectionOffsetTemp;
  212. MUSIC_TIME mtOldPatternEnd = (!fStart && !fLoop && pOldPattern) ? mtSectionOffset + (pOldPattern->m_wNumMeasures * mtOldMeasureTime) : 0;
  213. MUSIC_TIME mtNewPatternLength = pTargetPattern->m_wNumMeasures * mtMeasureTime;
  214. MUSIC_TIME mtOverlap = 0;
  215. if (m_mtOverlap && fDirty) // assumes 1 controlling segment w/command track at a time
  216. {
  217. if (m_pStyle->UsingDX8())
  218. {
  219. mtOverlap = mtMeasureTime - (m_mtOverlap % mtMeasureTime);
  220. }
  221. m_mtOverlap = 0;
  222. //TraceI(0, "[1]Overlap: %d\n", mtOverlap);
  223. }
  224. else if (mtNow < mtOldPatternEnd &&
  225. m_pStyle->UsingDX8() )
  226. {
  227. mtOverlap = mtOldPatternEnd - mtNow;
  228. if (fDirty)
  229. {
  230. m_mtOverlap = mtOverlap;
  231. mtOverlap = 0;
  232. }
  233. else
  234. {
  235. mtOverlap = (mtMeasureTime - (mtOverlap % mtMeasureTime)) % mtMeasureTime;
  236. }
  237. //TraceI(0, "[2]Overlap: %d\n", fDirty ? m_mtOverlap : mtOverlap);
  238. }
  239. // Whenever I get a new pattern, I should get a new chord
  240. GetNextChord(mtNow, mtOffset, pPerformance, fStart, fSkipVariations);
  241. /*
  242. if (fDirty)
  243. {
  244. m_mtSectionOffset = mtNow - mtOverlap;
  245. }
  246. else
  247. {
  248. m_mtSectionOffset = m_mtNextCommandTime - mtOverlap; // keep the section offset on a measure boundary
  249. }
  250. */
  251. m_mtSectionOffset = m_mtNextCommandTime;
  252. m_mtNextCommandTime = m_mtSectionOffset + mtNewPatternLength;
  253. // Note: at this point mtNextCommand == m_mtNextStyleTime - mtNow,
  254. // if that difference is smaller than the original value for mtNextCommand.
  255. if (mtNextCommand && m_mtNextCommandTime > mtNow + mtNextCommand)
  256. {
  257. m_mtNextCommandTime = mtNow + mtNextCommand;
  258. }
  259. TraceI(3, "Next Command Time: %d Measures: %d Measure time: %d\n",
  260. // TraceI(0, "Next Command Time: %d Measures: %d Measure time: %d\n",
  261. m_mtNextCommandTime, m_pPattern->m_wNumMeasures, mtMeasureTime);
  262. return S_OK;
  263. }
  264. else return E_POINTER;
  265. }
  266. MUSIC_TIME StyleTrackState::PartOffset(int nPartIndex)
  267. {
  268. return m_pmtPartOffset[nPartIndex] + m_mtSectionOffset;
  269. }
  270. /////////////////////////////////////////////////////////////////////////////
  271. // StyleTrackInfo
  272. StyleTrackInfo::StyleTrackInfo()
  273. {
  274. m_dwPatternTag = DMUS_PATTERN_STYLE;
  275. }
  276. StyleTrackInfo::~StyleTrackInfo()
  277. {
  278. }
  279. HRESULT StyleTrackInfo::Init(
  280. /*[in]*/ IDirectMusicSegment* pSegment
  281. )
  282. {
  283. HRESULT hr = S_OK;
  284. return hr;
  285. }
  286. HRESULT StyleTrackInfo::InitPlay(
  287. /*[in]*/ IDirectMusicTrack* pParentrack,
  288. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  289. /*[in]*/ IDirectMusicPerformance* pPerformance,
  290. /*[out]*/ void** ppStateData,
  291. /*[in]*/ DWORD dwTrackID,
  292. /*[in]*/ DWORD dwFlags
  293. )
  294. {
  295. IDirectMusicSegment* pSegment = NULL;
  296. StyleTrackState* pStateData = new StyleTrackState;
  297. if( NULL == pStateData )
  298. {
  299. return E_OUTOFMEMORY;
  300. }
  301. pStateData->m_dwValidate = m_dwValidate;
  302. StatePair SP(pSegmentState, pStateData);
  303. TListItem<StatePair>* pPair = new TListItem<StatePair>(SP);
  304. if (!pPair)
  305. {
  306. delete pStateData;
  307. return E_OUTOFMEMORY;
  308. }
  309. m_StateList.AddHead(pPair);
  310. pStateData->m_pTrack = pParentrack;
  311. pStateData->m_pPatternTrack = this;
  312. pStateData->m_dwVirtualTrackID = dwTrackID;
  313. pStateData->m_mtNextStyleTime = 0;
  314. pStateData->m_pStyle = pStateData->FindStyle(0, pStateData->m_mtNextStyleTime);
  315. if (!pStateData->m_pStyle)
  316. {
  317. delete pStateData;
  318. return E_POINTER;
  319. }
  320. pStateData->m_pPattern = NULL;
  321. pStateData->m_pSegState = pSegmentState; // weak reference, no addref.
  322. pStateData->m_pPerformance = pPerformance; // weak reference, no addref.
  323. pStateData->m_mtPerformanceOffset = 0;
  324. pStateData->m_mtCurrentChordTime = 0;
  325. pStateData->m_mtNextChordTime = 0;
  326. pStateData->m_mtPatternStart = 0;
  327. pStateData->m_mtSectionOffset = 0;
  328. pStateData->m_mtSectionOffsetTemp = 0;
  329. pStateData->m_mtOverlap = 0;
  330. HRESULT hr = pStateData->ResetMappings();
  331. if (FAILED(hr))
  332. {
  333. delete pStateData;
  334. return hr;
  335. }
  336. if (m_fStateSetBySetParam)
  337. {
  338. pStateData->m_fStateActive = m_fActive;
  339. }
  340. else
  341. {
  342. pStateData->m_fStateActive = !(dwFlags & (DMUS_SEGF_CONTROL | DMUS_SEGF_SECONDARY));
  343. }
  344. if (m_lRandomNumberSeed)
  345. {
  346. pStateData->InitVariationSeeds(m_lRandomNumberSeed);
  347. }
  348. if( SUCCEEDED( pSegmentState->GetSegment(&pSegment)))
  349. {
  350. if (FAILED(pSegment->GetTrackGroup(pStateData->m_pTrack, &pStateData->m_dwGroupID)))
  351. {
  352. pStateData->m_dwGroupID = 0xffffffff;
  353. }
  354. pSegment->Release();
  355. }
  356. *ppStateData = pStateData;
  357. return S_OK;
  358. }
  359. /////////////////////////////////////////////////////////////////////////////
  360. // CStyleTrack
  361. CStyleTrack::CStyleTrack() :
  362. m_bRequiresSave(0), m_cRef(1), m_fCSInitialized(FALSE)
  363. {
  364. InterlockedIncrement(&g_cComponent);
  365. ::InitializeCriticalSection( &m_CriticalSection );
  366. m_fCSInitialized = TRUE;
  367. srand((unsigned int)time(NULL));
  368. m_pTrackInfo = new StyleTrackInfo;
  369. // assert (m_pTrackInfo);
  370. }
  371. CStyleTrack::CStyleTrack(const CStyleTrack& rTrack, MUSIC_TIME mtStart, MUSIC_TIME mtEnd) :
  372. m_bRequiresSave(0), m_cRef(1), m_fCSInitialized(FALSE)
  373. {
  374. InterlockedIncrement(&g_cComponent);
  375. ::InitializeCriticalSection( &m_CriticalSection );
  376. m_fCSInitialized = TRUE;
  377. srand((unsigned int)time(NULL));
  378. m_pTrackInfo = new StyleTrackInfo((StyleTrackInfo*)rTrack.m_pTrackInfo, mtStart, mtEnd);
  379. }
  380. CStyleTrack::~CStyleTrack()
  381. {
  382. if (m_pTrackInfo)
  383. {
  384. delete m_pTrackInfo;
  385. }
  386. if (m_fCSInitialized)
  387. {
  388. ::DeleteCriticalSection( &m_CriticalSection );
  389. }
  390. InterlockedDecrement(&g_cComponent);
  391. }
  392. // CStyleTrack Methods
  393. STDMETHODIMP CStyleTrack::QueryInterface(
  394. const IID &iid,
  395. void **ppv)
  396. {
  397. V_INAME(CStyleTrack::QueryInterface);
  398. V_REFGUID(iid);
  399. V_PTRPTR_WRITE(ppv);
  400. if (iid == IID_IUnknown || iid == IID_IDirectMusicTrack || iid == IID_IDirectMusicTrack8)
  401. {
  402. *ppv = static_cast<IDirectMusicTrack*>(this);
  403. }
  404. else if (iid == IID_IPersistStream)
  405. {
  406. *ppv = static_cast<IPersistStream*>(this);
  407. }
  408. else if (iid == IID_IStyleTrack)
  409. {
  410. *ppv = static_cast<IStyleTrack*>(this);
  411. }
  412. else
  413. {
  414. *ppv = NULL;
  415. return E_NOINTERFACE;
  416. }
  417. reinterpret_cast<IUnknown*>(this)->AddRef();
  418. return S_OK;
  419. }
  420. STDMETHODIMP_(ULONG) CStyleTrack::AddRef()
  421. {
  422. return InterlockedIncrement(&m_cRef);
  423. }
  424. STDMETHODIMP_(ULONG) CStyleTrack::Release()
  425. {
  426. if (!InterlockedDecrement(&m_cRef))
  427. {
  428. delete this;
  429. return 0;
  430. }
  431. return m_cRef;
  432. }
  433. //////////////////////////////////////////////////////////////////////
  434. // IDirectMusicTrack::Init
  435. HRESULT CStyleTrack::Init(
  436. /* [in] */ IDirectMusicSegment __RPC_FAR *pSegment)
  437. {
  438. V_INAME(CStyleTrack::Init);
  439. V_INTERFACE(pSegment);
  440. HRESULT hr = S_OK;
  441. if (m_pTrackInfo == NULL)
  442. return DMUS_E_NOT_INIT;
  443. EnterCriticalSection( &m_CriticalSection );
  444. hr = m_pTrackInfo->MergePChannels();
  445. if (SUCCEEDED(hr))
  446. {
  447. pSegment->SetPChannelsUsed(m_pTrackInfo->m_dwPChannels, m_pTrackInfo->m_pdwPChannels);
  448. hr = m_pTrackInfo->Init(pSegment);
  449. }
  450. LeaveCriticalSection( &m_CriticalSection );
  451. return hr;
  452. }
  453. HRESULT CStyleTrack::InitPlay(
  454. /*[in]*/ IDirectMusicSegmentState* pSegmentState,
  455. /*[in]*/ IDirectMusicPerformance* pPerformance,
  456. /*[out]*/ void** ppStateData,
  457. /*[in]*/ DWORD dwTrackID,
  458. /*[in]*/ DWORD dwFlags
  459. )
  460. {
  461. V_INAME(CStyleTrack::InitPlay);
  462. V_PTRPTR_WRITE(ppStateData);
  463. V_INTERFACE(pSegmentState);
  464. V_INTERFACE(pPerformance);
  465. HRESULT hr = S_OK;
  466. EnterCriticalSection( &m_CriticalSection );
  467. if (m_pTrackInfo == NULL)
  468. {
  469. LeaveCriticalSection( &m_CriticalSection );
  470. return DMUS_E_NOT_INIT;
  471. }
  472. hr = m_pTrackInfo->InitPlay(this, pSegmentState, pPerformance, ppStateData, dwTrackID, dwFlags);
  473. LeaveCriticalSection( &m_CriticalSection );
  474. return hr;
  475. }
  476. HRESULT CStyleTrack::EndPlay(
  477. /*[in]*/ void* pStateData
  478. )
  479. {
  480. V_INAME(CStyleTrack::EndPlay);
  481. V_BUFPTR_WRITE(pStateData, sizeof(StyleTrackState));
  482. HRESULT hr = DMUS_E_NOT_INIT;
  483. StyleTrackState* pSD = (StyleTrackState*)pStateData;
  484. EnterCriticalSection( &m_CriticalSection );
  485. // if (pSD->m_pPattern) pSD->m_pPattern->Release();
  486. if (m_pTrackInfo) hr = m_pTrackInfo->EndPlay(pSD);
  487. LeaveCriticalSection( &m_CriticalSection );
  488. return hr;
  489. }
  490. HRESULT CStyleTrack::Play(
  491. /*[in]*/ void* pStateData,
  492. /*[in]*/ MUSIC_TIME mtStart,
  493. /*[in]*/ MUSIC_TIME mtEnd,
  494. /*[in]*/ MUSIC_TIME mtOffset,
  495. DWORD dwFlags,
  496. IDirectMusicPerformance* pPerf,
  497. IDirectMusicSegmentState* pSegState,
  498. DWORD dwVirtualID
  499. )
  500. {
  501. V_INAME(CStyleTrack::Play);
  502. V_BUFPTR_WRITE( pStateData, sizeof(StyleTrackState));
  503. V_INTERFACE(pPerf);
  504. V_INTERFACE(pSegState);
  505. HRESULT hr = DMUS_E_NOT_INIT;
  506. BOOL fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
  507. BOOL fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
  508. BOOL fControl = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
  509. EnterCriticalSection( &m_CriticalSection );
  510. if (!m_pTrackInfo)
  511. {
  512. LeaveCriticalSection( &m_CriticalSection );
  513. return hr;
  514. }
  515. StyleTrackState* pSD = (StyleTrackState *)pStateData;
  516. if (pSD->m_hrPlayCode == E_OUTOFMEMORY)
  517. {
  518. LeaveCriticalSection( &m_CriticalSection );
  519. return pSD->m_hrPlayCode;
  520. }
  521. if (pSD->m_dwValidate != m_pTrackInfo->m_dwValidate)
  522. {
  523. // new style added to track either via SetParam or Load. Resync state data.
  524. pSD->m_pStyle = pSD->FindStyle(mtStart, pSD->m_mtNextStyleTime);
  525. if (!pSD->m_pStyle)
  526. {
  527. hr = E_POINTER;
  528. }
  529. pSD->m_dwValidate = m_pTrackInfo->m_dwValidate;
  530. }
  531. if ((hr == DMUS_E_NOT_INIT) && pSD && pSD->m_pMappings)
  532. {
  533. if (fStart || fSeek || fControl)
  534. {
  535. pSD->m_mtSectionOffsetTemp = pSD->m_mtSectionOffset;
  536. pSD->m_mtSectionOffset = 0;
  537. pSD->m_mtNextCommandTemp = pSD->m_mtNextCommandTime;
  538. pSD->m_mtNextCommandTime = 0;
  539. pSD->m_pStyle = pSD->FindStyle(0, pSD->m_mtNextStyleTime);
  540. if (!pSD->m_pStyle)
  541. {
  542. hr = E_POINTER;
  543. }
  544. else
  545. {
  546. if (pSD->m_fStateActive) // if timesig events are enabled...
  547. {
  548. pSD->SendTimeSigMessage(mtStart, mtOffset, pSD->m_mtNextStyleTime, pPerf);
  549. }
  550. pSD->m_mtCurrentChordTime = 0;
  551. pSD->m_mtNextChordTime = 0;
  552. pSD->m_mtLaterChordTime = 0;
  553. // pSD->m_CurrentChord.bSubChordCount = 0;
  554. pSD->m_mtPatternStart = 0;
  555. for (DWORD dw = 0; dw < m_pTrackInfo->m_dwPChannels; dw++)
  556. {
  557. pSD->m_pMappings[dw].m_mtTime = 0;
  558. pSD->m_pMappings[dw].m_dwPChannelMap = m_pTrackInfo->m_pdwPChannels[dw];
  559. pSD->m_pMappings[dw].m_fMute = FALSE;
  560. }
  561. }
  562. }
  563. hr = ((StyleTrackState *)pStateData)->Play(mtStart, mtEnd, mtOffset, 0, pPerf, dwFlags, FALSE);
  564. }
  565. LeaveCriticalSection( &m_CriticalSection );
  566. return hr;
  567. }
  568. HRESULT CStyleTrack::GetPriority(
  569. /*[out]*/ DWORD* pPriority
  570. )
  571. {
  572. return E_NOTIMPL;
  573. }
  574. HRESULT CStyleTrack::GetParam(
  575. REFGUID rCommandGuid,
  576. MUSIC_TIME mtTime,
  577. MUSIC_TIME* pmtNext,
  578. void* pData,
  579. void* pStateData)
  580. {
  581. V_INAME(CStyleTrack::GetParam);
  582. V_PTR_WRITE_OPT(pmtNext,MUSIC_TIME);
  583. V_PTR_WRITE(pData,1);
  584. V_PTR_WRITE_OPT(pStateData,1);
  585. V_REFGUID(rCommandGuid);
  586. HRESULT hr;
  587. EnterCriticalSection( &m_CriticalSection );
  588. bool fInCritSection = true;
  589. if (rCommandGuid == GUID_IDirectMusicStyle)
  590. {
  591. if (m_pTrackInfo)
  592. {
  593. TListItem<StylePair>* pScan = m_pTrackInfo->m_pISList.GetHead();
  594. if (pScan)
  595. {
  596. IDMStyle* pStyle = pScan->GetItemValue().m_pStyle;
  597. for(pScan = pScan->GetNext(); pScan; pScan = pScan->GetNext())
  598. {
  599. StylePair& rScan = pScan->GetItemValue();
  600. if (mtTime < rScan.m_mtTime && rScan.m_pStyle) break; // ignore if NULL
  601. if (rScan.m_pStyle) pStyle = rScan.m_pStyle; // skip if NULL
  602. }
  603. IDirectMusicStyle* pDMStyle;
  604. if (!pStyle)
  605. {
  606. hr = E_POINTER;
  607. }
  608. else
  609. {
  610. pStyle->QueryInterface(IID_IDirectMusicStyle, (void**)&pDMStyle);
  611. // Note: QI with no Release has the effect of an AddRef
  612. *(IDirectMusicStyle**)pData = pDMStyle;
  613. if (pmtNext)
  614. {
  615. *pmtNext = (pScan != NULL) ? pScan->GetItemValue().m_mtTime - mtTime : 0;
  616. }
  617. hr = S_OK;
  618. }
  619. }
  620. else hr = DMUS_E_NOT_FOUND;
  621. }
  622. else hr = DMUS_E_NOT_INIT;
  623. }
  624. else if (rCommandGuid == GUID_TimeSignature)
  625. {
  626. // find the style at the given time, and return its time sig.
  627. if (m_pTrackInfo)
  628. {
  629. TListItem<StylePair>* pScan = m_pTrackInfo->m_pISList.GetHead();
  630. if (pScan)
  631. {
  632. IDMStyle* pStyle = pScan->GetItemValue().m_pStyle;
  633. MUSIC_TIME mtStyleTime = pScan->GetItemValue().m_mtTime;
  634. for(pScan = pScan->GetNext(); pScan; pScan = pScan->GetNext())
  635. {
  636. StylePair& rScan = pScan->GetItemValue();
  637. if (mtTime < rScan.m_mtTime) break;
  638. pStyle = rScan.m_pStyle;
  639. mtStyleTime = rScan.m_mtTime;
  640. }
  641. if (!pStyle)
  642. {
  643. hr = E_POINTER;
  644. }
  645. else
  646. {
  647. // Enter the style's CritSec
  648. pStyle->CritSec(true);
  649. // If I've got state data, use it to get the time signature of the pattern at mtTime
  650. if (pStateData)
  651. {
  652. MUSIC_TIME mtMeasureTime = 0;
  653. MUSIC_TIME mtNext = 0;
  654. CDirectMusicPattern* pTargetPattern;
  655. StyleTrackState* pStyleTrackState = (StyleTrackState*)pStateData;
  656. IDirectMusicPerformance* pPerformance = pStyleTrackState->m_pPerformance;
  657. MUSIC_TIME mtOffset = pStyleTrackState->m_mtPerformanceOffset;
  658. DMStyleStruct* pStyleStruct = NULL;
  659. hr = pStyle->GetStyleInfo((void**)&pStyleStruct);
  660. if (SUCCEEDED(hr))
  661. {
  662. // I don't need the Track CritSec any more, and in fact there's an almost
  663. // guaranteed deadlock if I keep it, so get rid of it
  664. LeaveCriticalSection( &m_CriticalSection );
  665. fInCritSection = false;
  666. hr = pStyleStruct->GetPattern(true, mtTime, mtOffset, NULL,
  667. pPerformance, NULL, pTargetPattern, mtMeasureTime, mtNext);
  668. if (SUCCEEDED(hr))
  669. {
  670. DMUS_TIMESIGNATURE* pTimeSig = (DMUS_TIMESIGNATURE*)pData;
  671. *pTimeSig = pTargetPattern->TimeSignature(pStyleStruct);
  672. pTimeSig->mtTime = mtStyleTime - mtTime;
  673. //TraceI(0, "New Time sig from pattern...\n");
  674. if (pmtNext)
  675. {
  676. *pmtNext = mtNext;
  677. }
  678. }
  679. }
  680. }
  681. else // Just get the style's time signature
  682. {
  683. IDirectMusicStyle* pDMStyle;
  684. hr = pStyle->QueryInterface(IID_IDirectMusicStyle, (void**)&pDMStyle);
  685. if (SUCCEEDED(hr))
  686. {
  687. hr = pDMStyle->GetTimeSignature((DMUS_TIMESIGNATURE*)pData);
  688. if (SUCCEEDED(hr))
  689. {
  690. ((DMUS_TIMESIGNATURE*)pData)->mtTime = mtStyleTime - mtTime;
  691. if (pmtNext)
  692. {
  693. *pmtNext = (pScan != NULL) ? pScan->GetItemValue().m_mtTime : 0;
  694. }
  695. }
  696. pDMStyle->Release();
  697. }
  698. }
  699. // Leave the style's CritSec
  700. pStyle->CritSec(false);
  701. }
  702. }
  703. else hr = DMUS_E_NOT_FOUND;
  704. }
  705. else hr = DMUS_E_NOT_INIT;
  706. }
  707. else if (rCommandGuid == GUID_SegmentTimeSig)
  708. {
  709. SegmentTimeSig* pTimeSigParam = (SegmentTimeSig*)pData;
  710. if (!pTimeSigParam->pSegment) hr = E_POINTER;
  711. // find the style at the given time, and return the time sig currently in effect in the segment.
  712. else if (m_pTrackInfo)
  713. {
  714. TListItem<StylePair>* pScan = m_pTrackInfo->m_pISList.GetHead();
  715. if (pScan)
  716. {
  717. IDMStyle* pStyle = pScan->GetItemValue().m_pStyle;
  718. MUSIC_TIME mtStyleTime = pScan->GetItemValue().m_mtTime;
  719. for(pScan = pScan->GetNext(); pScan; pScan = pScan->GetNext())
  720. {
  721. StylePair& rScan = pScan->GetItemValue();
  722. if (mtTime < rScan.m_mtTime) break;
  723. pStyle = rScan.m_pStyle;
  724. mtStyleTime = rScan.m_mtTime;
  725. }
  726. if (!pStyle)
  727. {
  728. hr = E_POINTER;
  729. }
  730. else
  731. {
  732. DMStyleStruct* pStyleStruct = NULL;
  733. hr = pStyle->GetStyleInfo((void**)&pStyleStruct);
  734. if (SUCCEEDED(hr))
  735. {
  736. CDirectMusicPattern* pPattern = NULL;
  737. MUSIC_TIME mtMeasureTime = 0, mtNextCommand = 0;
  738. hr = pStyleStruct->GetPattern(true, mtTime, 0, NULL, NULL, pTimeSigParam->pSegment,
  739. pPattern, mtMeasureTime, mtNextCommand);
  740. if (SUCCEEDED(hr))
  741. {
  742. pTimeSigParam->TimeSig = pPattern->m_timeSig;
  743. pTimeSigParam->TimeSig.mtTime = mtStyleTime - mtTime;
  744. if (pmtNext)
  745. {
  746. *pmtNext = (mtNextCommand) ? mtNextCommand - mtTime : 0;
  747. }
  748. }
  749. }
  750. }
  751. }
  752. else hr = DMUS_E_NOT_FOUND;
  753. }
  754. else hr = DMUS_E_NOT_INIT;
  755. }
  756. else
  757. {
  758. hr = DMUS_E_GET_UNSUPPORTED;
  759. }
  760. if (fInCritSection) LeaveCriticalSection( &m_CriticalSection );
  761. return hr;
  762. }
  763. HRESULT CStyleTrack::SetParam(
  764. REFGUID rCommandGuid,
  765. MUSIC_TIME mtTime,
  766. void __RPC_FAR *pData)
  767. {
  768. V_INAME(CStyleTrack::SetParam);
  769. V_PTR_WRITE_OPT(pData,1);
  770. V_REFGUID(rCommandGuid);
  771. HRESULT hr = S_OK;
  772. EnterCriticalSection( &m_CriticalSection );
  773. if (!m_pTrackInfo)
  774. {
  775. hr = DMUS_E_NOT_INIT;
  776. }
  777. else if (rCommandGuid == GUID_IDirectMusicStyle)
  778. {
  779. if (!pData)
  780. {
  781. hr = E_POINTER;
  782. }
  783. else
  784. {
  785. IDirectMusicStyle* pStyle = (IDirectMusicStyle*)pData;
  786. IDMStyle* pIS = NULL;
  787. pStyle->QueryInterface(IID_IDMStyle, (void**)&pIS);
  788. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  789. if (!pNew)
  790. {
  791. hr = E_OUTOFMEMORY;
  792. }
  793. else
  794. {
  795. pNew->GetItemValue().m_mtTime = mtTime;
  796. pNew->GetItemValue().m_pStyle = pIS;
  797. m_pTrackInfo->m_pISList.AddTail(pNew);
  798. m_pTrackInfo->m_dwValidate++;
  799. hr = m_pTrackInfo->MergePChannels();
  800. }
  801. }
  802. }
  803. else if( rCommandGuid == GUID_EnableTimeSig )
  804. {
  805. if( m_pTrackInfo->m_fStateSetBySetParam && m_pTrackInfo->m_fActive )
  806. {
  807. hr = DMUS_E_TYPE_DISABLED;
  808. }
  809. else
  810. {
  811. m_pTrackInfo->m_fStateSetBySetParam = TRUE;
  812. m_pTrackInfo->m_fActive = TRUE;
  813. hr = S_OK;
  814. }
  815. }
  816. else if( rCommandGuid == GUID_DisableTimeSig )
  817. {
  818. if( m_pTrackInfo->m_fStateSetBySetParam && !m_pTrackInfo->m_fActive )
  819. {
  820. hr = DMUS_E_TYPE_DISABLED;
  821. }
  822. else
  823. {
  824. m_pTrackInfo->m_fStateSetBySetParam = TRUE;
  825. m_pTrackInfo->m_fActive = FALSE;
  826. hr = S_OK;
  827. }
  828. }
  829. else if ( rCommandGuid == GUID_SeedVariations )
  830. {
  831. if (pData)
  832. {
  833. m_pTrackInfo->m_lRandomNumberSeed = *((long*) pData);
  834. hr = S_OK;
  835. }
  836. else hr = E_POINTER;
  837. }
  838. else
  839. {
  840. hr = DMUS_E_SET_UNSUPPORTED;
  841. }
  842. LeaveCriticalSection( &m_CriticalSection );
  843. return hr;
  844. }
  845. // IPersist methods
  846. HRESULT CStyleTrack::GetClassID( LPCLSID pClassID )
  847. {
  848. V_INAME(CStyleTrack::GetClassID);
  849. V_PTR_WRITE(pClassID, CLSID);
  850. *pClassID = CLSID_DirectMusicStyleTrack;
  851. return S_OK;
  852. }
  853. HRESULT CStyleTrack::IsParamSupported(
  854. /*[in]*/ REFGUID rGuid
  855. )
  856. {
  857. V_INAME(CStyleTrack::IsParamSupported);
  858. V_REFGUID(rGuid);
  859. if (!m_pTrackInfo)
  860. {
  861. return DMUS_E_NOT_INIT;
  862. }
  863. if (rGuid == GUID_IDirectMusicStyle ||
  864. rGuid == GUID_SeedVariations ||
  865. rGuid == GUID_SegmentTimeSig )
  866. {
  867. return S_OK;
  868. }
  869. else if (m_pTrackInfo->m_fStateSetBySetParam)
  870. {
  871. if( m_pTrackInfo->m_fActive )
  872. {
  873. if( rGuid == GUID_DisableTimeSig ) return S_OK;
  874. if( rGuid == GUID_TimeSignature ) return S_OK;
  875. if( rGuid == GUID_EnableTimeSig ) return DMUS_E_TYPE_DISABLED;
  876. }
  877. else
  878. {
  879. if( rGuid == GUID_EnableTimeSig ) return S_OK;
  880. if( rGuid == GUID_DisableTimeSig ) return DMUS_E_TYPE_DISABLED;
  881. if( rGuid == GUID_TimeSignature ) return DMUS_E_TYPE_DISABLED;
  882. }
  883. }
  884. else
  885. {
  886. if( ( rGuid == GUID_DisableTimeSig ) ||
  887. ( rGuid == GUID_TimeSignature ) ||
  888. ( rGuid == GUID_EnableTimeSig )) return S_OK;
  889. }
  890. return DMUS_E_TYPE_UNSUPPORTED;
  891. }
  892. // IPersistStream methods
  893. HRESULT CStyleTrack::IsDirty()
  894. {
  895. return m_bRequiresSave ? S_OK : S_FALSE;
  896. }
  897. HRESULT CStyleTrack::Save( LPSTREAM pStream, BOOL fClearDirty )
  898. {
  899. return E_NOTIMPL;
  900. }
  901. HRESULT CStyleTrack::GetSizeMax( ULARGE_INTEGER* /*pcbSize*/ )
  902. {
  903. return E_NOTIMPL;
  904. }
  905. BOOL Less(StylePair& SP1, StylePair& SP2)
  906. { return SP1.m_mtTime < SP2.m_mtTime; }
  907. HRESULT CStyleTrack::Load(LPSTREAM pStream )
  908. {
  909. V_INAME(CStyleTrack::Load);
  910. V_INTERFACE(pStream);
  911. IAARIFFStream* pIRiffStream;
  912. //MMCKINFO ckMain;
  913. MMCKINFO ck;
  914. HRESULT hr = E_FAIL;
  915. EnterCriticalSection( &m_CriticalSection );
  916. if (!m_pTrackInfo)
  917. {
  918. LeaveCriticalSection( &m_CriticalSection );
  919. return DMUS_E_NOT_INIT;
  920. }
  921. StyleTrackInfo* pTrackInfo = (StyleTrackInfo*)m_pTrackInfo;
  922. if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_STYLE)
  923. {
  924. LeaveCriticalSection( &m_CriticalSection );
  925. return E_FAIL;
  926. }
  927. pTrackInfo->m_pISList.CleanUp();
  928. if( SUCCEEDED( AllocRIFFStream( pStream, &pIRiffStream ) ) )
  929. {
  930. if (pIRiffStream->Descend( &ck, NULL, 0 ) == 0)
  931. {
  932. if (ck.ckid == FOURCC_LIST && ck.fccType == DMUS_FOURCC_STYLE_TRACK_LIST)
  933. {
  934. hr = pTrackInfo->LoadStyleRefList(pIRiffStream, &ck);
  935. }
  936. pIRiffStream->Ascend( &ck, 0 );
  937. }
  938. pIRiffStream->Release();
  939. }
  940. if (SUCCEEDED(hr))
  941. {
  942. pTrackInfo->m_pISList.MergeSort(Less);
  943. m_pTrackInfo->m_dwValidate++;
  944. hr = m_pTrackInfo->MergePChannels();
  945. }
  946. LeaveCriticalSection( &m_CriticalSection );
  947. return hr;
  948. }
  949. HRESULT StyleTrackInfo::LoadStyleRefList( IAARIFFStream* pIRiffStream, MMCKINFO* pckParent )
  950. {
  951. HRESULT hr = S_OK;
  952. HRESULT hrStyle = E_FAIL;
  953. if (!pIRiffStream || !pckParent) return E_INVALIDARG;
  954. MMCKINFO ck;
  955. while ( pIRiffStream->Descend( &ck, pckParent, 0 ) == 0 )
  956. {
  957. if ( ck.ckid == FOURCC_LIST && ck.fccType == DMUS_FOURCC_STYLE_REF_LIST )
  958. {
  959. hr = LoadStyleRef(pIRiffStream, &ck);
  960. if (hr == S_OK)
  961. {
  962. hrStyle = hr;
  963. }
  964. pIRiffStream->Ascend( &ck, 0 );
  965. }
  966. pIRiffStream->Ascend( &ck, 0 );
  967. }
  968. if (hr != S_OK && hrStyle == S_OK)
  969. {
  970. hr = hrStyle;
  971. }
  972. return hr;
  973. }
  974. HRESULT StyleTrackInfo::LoadStyleRef( IAARIFFStream* pIRiffStream, MMCKINFO* pckParent )
  975. {
  976. HRESULT hr = S_OK;
  977. HRESULT hrStyle = S_OK;
  978. if (!pIRiffStream || !pckParent) return E_INVALIDARG;
  979. MMCKINFO ck;
  980. IStream* pIStream = pIRiffStream->GetStream();
  981. if(!pIStream) return E_FAIL;
  982. IDMStyle* pStyle = NULL;
  983. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  984. if (!pNew) return E_OUTOFMEMORY;
  985. StylePair& rNew = pNew->GetItemValue();
  986. while (pIRiffStream->Descend( &ck, pckParent, 0 ) == 0)
  987. {
  988. switch (ck.ckid)
  989. {
  990. case DMUS_FOURCC_TIME_STAMP_CHUNK:
  991. {
  992. DWORD dwTime;
  993. DWORD cb;
  994. hr = pIStream->Read( &dwTime, sizeof( dwTime ), &cb );
  995. if (FAILED(hr) || cb != sizeof( dwTime ) )
  996. {
  997. if (SUCCEEDED(hr)) hr = E_FAIL;
  998. pIRiffStream->Ascend( &ck, 0 );
  999. goto ON_END;
  1000. }
  1001. rNew.m_mtTime = dwTime;
  1002. }
  1003. break;
  1004. case FOURCC_LIST:
  1005. if (ck.fccType == DMUS_FOURCC_REF_LIST)
  1006. {
  1007. hr = LoadReference(pIStream, pIRiffStream, ck, &pStyle);
  1008. if (hr != S_OK)
  1009. {
  1010. hrStyle = hr;
  1011. }
  1012. if (SUCCEEDED(hr))
  1013. {
  1014. rNew.m_pStyle = pStyle;
  1015. }
  1016. }
  1017. break;
  1018. }
  1019. pIRiffStream->Ascend( &ck, 0 );
  1020. }
  1021. if (SUCCEEDED(hr))
  1022. {
  1023. m_pISList.AddTail(pNew);
  1024. }
  1025. else
  1026. {
  1027. delete pNew;
  1028. }
  1029. ON_END:
  1030. pIStream->Release();
  1031. if (hr == S_OK && hrStyle != S_OK)
  1032. {
  1033. hr = hrStyle;
  1034. }
  1035. return hr;
  1036. }
  1037. //////////////////////////////////////////////////////////////////////
  1038. // StyleTrackInfo::LoadReference
  1039. HRESULT StyleTrackInfo::LoadReference(IStream *pStream,
  1040. IAARIFFStream *pIRiffStream,
  1041. MMCKINFO& ckParent,
  1042. IDMStyle** ppStyle)
  1043. {
  1044. if (!pStream || !pIRiffStream || !ppStyle) return E_INVALIDARG;
  1045. IDirectMusicLoader* pLoader = NULL;
  1046. IDirectMusicGetLoader *pIGetLoader;
  1047. HRESULT hr = pStream->QueryInterface( IID_IDirectMusicGetLoader,(void **) &pIGetLoader );
  1048. if (FAILED(hr)) return hr;
  1049. hr = pIGetLoader->GetLoader(&pLoader);
  1050. pIGetLoader->Release();
  1051. if (FAILED(hr)) return hr;
  1052. DMUS_OBJECTDESC desc;
  1053. ZeroMemory(&desc, sizeof(desc));
  1054. DWORD cbRead;
  1055. MMCKINFO ckNext;
  1056. ckNext.ckid = 0;
  1057. ckNext.fccType = 0;
  1058. DWORD dwSize = 0;
  1059. while( pIRiffStream->Descend( &ckNext, &ckParent, 0 ) == 0 )
  1060. {
  1061. switch(ckNext.ckid)
  1062. {
  1063. case DMUS_FOURCC_REF_CHUNK:
  1064. DMUS_IO_REFERENCE ioDMRef;
  1065. hr = pStream->Read(&ioDMRef, sizeof(DMUS_IO_REFERENCE), &cbRead);
  1066. if(SUCCEEDED(hr) && cbRead == sizeof(DMUS_IO_REFERENCE))
  1067. {
  1068. desc.guidClass = ioDMRef.guidClassID;
  1069. desc.dwValidData |= ioDMRef.dwValidData;
  1070. desc.dwValidData |= DMUS_OBJ_CLASS;
  1071. }
  1072. else if(SUCCEEDED(hr))
  1073. {
  1074. hr = E_FAIL;
  1075. }
  1076. break;
  1077. case DMUS_FOURCC_GUID_CHUNK:
  1078. hr = pStream->Read(&(desc.guidObject), sizeof(GUID), &cbRead);
  1079. if(SUCCEEDED(hr) && cbRead == sizeof(GUID))
  1080. {
  1081. desc.dwValidData |= DMUS_OBJ_OBJECT;
  1082. }
  1083. else if(SUCCEEDED(hr))
  1084. {
  1085. hr = E_FAIL;
  1086. }
  1087. break;
  1088. case DMUS_FOURCC_DATE_CHUNK:
  1089. hr = pStream->Read(&(desc.ftDate), sizeof(FILETIME), &cbRead);
  1090. if(SUCCEEDED(hr) && cbRead == sizeof(FILETIME))
  1091. {
  1092. desc.dwValidData |= DMUS_OBJ_DATE;
  1093. }
  1094. else if(SUCCEEDED(hr))
  1095. {
  1096. hr = E_FAIL;
  1097. }
  1098. break;
  1099. case DMUS_FOURCC_NAME_CHUNK:
  1100. dwSize = min(sizeof(desc.wszName), ckNext.cksize);
  1101. hr = pStream->Read(desc.wszName, dwSize, &cbRead);
  1102. if(SUCCEEDED(hr) && cbRead == dwSize)
  1103. {
  1104. desc.wszName[DMUS_MAX_NAME - 1] = L'\0';
  1105. desc.dwValidData |= DMUS_OBJ_NAME;
  1106. }
  1107. else if(SUCCEEDED(hr))
  1108. {
  1109. hr = E_FAIL;
  1110. }
  1111. break;
  1112. case DMUS_FOURCC_FILE_CHUNK:
  1113. dwSize = min(sizeof(desc.wszFileName), ckNext.cksize);
  1114. hr = pStream->Read(desc.wszFileName, dwSize, &cbRead);
  1115. if(SUCCEEDED(hr) && cbRead == dwSize)
  1116. {
  1117. desc.wszFileName[DMUS_MAX_FILENAME - 1] = L'\0';
  1118. desc.dwValidData |= DMUS_OBJ_FILENAME;
  1119. }
  1120. else if(SUCCEEDED(hr))
  1121. {
  1122. hr = E_FAIL;
  1123. }
  1124. break;
  1125. case DMUS_FOURCC_CATEGORY_CHUNK:
  1126. dwSize = min(sizeof(desc.wszCategory), ckNext.cksize);
  1127. hr = pStream->Read(desc.wszCategory, dwSize, &cbRead);
  1128. if(SUCCEEDED(hr) && cbRead == dwSize)
  1129. {
  1130. desc.wszCategory[DMUS_MAX_CATEGORY - 1] = L'\0';
  1131. desc.dwValidData |= DMUS_OBJ_CATEGORY;
  1132. }
  1133. else if(SUCCEEDED(hr))
  1134. {
  1135. hr = E_FAIL;
  1136. }
  1137. break;
  1138. case DMUS_FOURCC_VERSION_CHUNK:
  1139. DMUS_IO_VERSION ioDMObjVer;
  1140. hr = pStream->Read(&ioDMObjVer, sizeof(DMUS_IO_VERSION), &cbRead);
  1141. if(SUCCEEDED(hr) && cbRead == sizeof(DMUS_IO_VERSION))
  1142. {
  1143. desc.vVersion.dwVersionMS = ioDMObjVer.dwVersionMS;
  1144. desc.vVersion.dwVersionLS = ioDMObjVer.dwVersionLS;
  1145. desc.dwValidData |= DMUS_OBJ_VERSION;
  1146. }
  1147. else if(SUCCEEDED(hr))
  1148. {
  1149. hr = E_FAIL;
  1150. }
  1151. break;
  1152. default:
  1153. break;
  1154. }
  1155. if(SUCCEEDED(hr) && pIRiffStream->Ascend(&ckNext, 0) == 0)
  1156. {
  1157. ckNext.ckid = 0;
  1158. ckNext.fccType = 0;
  1159. }
  1160. else if (SUCCEEDED(hr)) hr = E_FAIL;
  1161. }
  1162. if(SUCCEEDED(hr))
  1163. {
  1164. desc.dwSize = sizeof(DMUS_OBJECTDESC);
  1165. hr = pLoader->GetObject(&desc, IID_IDMStyle, (void**)ppStyle);
  1166. if(SUCCEEDED(hr))
  1167. {
  1168. DMStyleStruct* pStyle;
  1169. (*ppStyle)->GetStyleInfo((void **)&pStyle);
  1170. TListItem<DirectMusicPart*>* pPart;
  1171. for(pPart = pStyle->m_PartList.GetHead(); pPart != NULL; pPart = pPart->GetNext())
  1172. {
  1173. DirectMusicPart* pPattern = pPart->GetItemValue();
  1174. DirectMusicTimeSig& TimeSig =
  1175. pPattern->m_timeSig.m_bBeat == 0 ? pStyle->m_TimeSignature : pPattern->m_timeSig;
  1176. pPattern->EventList.MergeSort(TimeSig);
  1177. }
  1178. }
  1179. }
  1180. if (pLoader)
  1181. {
  1182. pLoader->Release();
  1183. }
  1184. return hr;
  1185. }
  1186. HRESULT STDMETHODCALLTYPE CStyleTrack::AddNotificationType(
  1187. /* [in] */ REFGUID rGuidNotify)
  1188. {
  1189. V_INAME(CStyleTrack::AddNotificationType);
  1190. V_REFGUID(rGuidNotify);
  1191. HRESULT hr = S_OK;
  1192. EnterCriticalSection( &m_CriticalSection );
  1193. if (m_pTrackInfo)
  1194. hr = m_pTrackInfo->AddNotificationType(rGuidNotify);
  1195. else
  1196. hr = DMUS_E_NOT_INIT;
  1197. LeaveCriticalSection( &m_CriticalSection );
  1198. return hr;
  1199. }
  1200. HRESULT STDMETHODCALLTYPE CStyleTrack::RemoveNotificationType(
  1201. /* [in] */ REFGUID rGuidNotify)
  1202. {
  1203. V_INAME(CStyleTrack::RemoveNotificationType);
  1204. V_REFGUID(rGuidNotify);
  1205. HRESULT hr = S_OK;
  1206. EnterCriticalSection( &m_CriticalSection );
  1207. if (m_pTrackInfo)
  1208. hr = m_pTrackInfo->RemoveNotificationType(rGuidNotify);
  1209. else
  1210. hr = DMUS_E_NOT_INIT;
  1211. LeaveCriticalSection( &m_CriticalSection );
  1212. return hr;
  1213. }
  1214. HRESULT STDMETHODCALLTYPE CStyleTrack::Clone(
  1215. MUSIC_TIME mtStart,
  1216. MUSIC_TIME mtEnd,
  1217. IDirectMusicTrack** ppTrack)
  1218. {
  1219. V_INAME(CStyleTrack::Clone);
  1220. V_PTRPTR_WRITE(ppTrack);
  1221. HRESULT hr = S_OK;
  1222. if(mtStart < 0 )
  1223. {
  1224. return E_INVALIDARG;
  1225. }
  1226. if(mtStart > mtEnd)
  1227. {
  1228. return E_INVALIDARG;
  1229. }
  1230. EnterCriticalSection( &m_CriticalSection );
  1231. CStyleTrack *pDM;
  1232. try
  1233. {
  1234. pDM = new CStyleTrack(*this, mtStart, mtEnd);
  1235. }
  1236. catch( ... )
  1237. {
  1238. pDM = NULL;
  1239. }
  1240. if (pDM == NULL) {
  1241. LeaveCriticalSection( &m_CriticalSection );
  1242. return E_OUTOFMEMORY;
  1243. }
  1244. hr = pDM->QueryInterface(IID_IDirectMusicTrack, (void**)ppTrack);
  1245. pDM->Release();
  1246. LeaveCriticalSection( &m_CriticalSection );
  1247. return hr;
  1248. }
  1249. STDMETHODIMP CStyleTrack::SetTrack(IUnknown* pStyle)
  1250. {
  1251. if (!pStyle) return E_POINTER;
  1252. EnterCriticalSection( &m_CriticalSection );
  1253. if (!m_pTrackInfo)
  1254. {
  1255. LeaveCriticalSection( &m_CriticalSection );
  1256. return DMUS_E_NOT_INIT;
  1257. }
  1258. IDMStyle* pIS = NULL;
  1259. pStyle->QueryInterface(IID_IDMStyle, (void**)&pIS);
  1260. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  1261. if (!pNew)
  1262. {
  1263. LeaveCriticalSection( &m_CriticalSection );
  1264. return E_OUTOFMEMORY;
  1265. }
  1266. pNew->GetItemValue().m_mtTime = 0;
  1267. pNew->GetItemValue().m_pStyle = pIS;
  1268. m_pTrackInfo->m_pISList.AddTail(pNew);
  1269. if (pIS) pIS->Release();
  1270. LeaveCriticalSection( &m_CriticalSection );
  1271. return S_OK;
  1272. }
  1273. // this gets the first style in the track's list.
  1274. STDMETHODIMP CStyleTrack::GetStyle(IUnknown * * ppStyle)
  1275. {
  1276. HRESULT hr;
  1277. EnterCriticalSection( &m_CriticalSection );
  1278. if (!m_pTrackInfo)
  1279. {
  1280. LeaveCriticalSection( &m_CriticalSection );
  1281. return DMUS_E_NOT_INIT;
  1282. }
  1283. TListItem<StylePair>* pHead = m_pTrackInfo->m_pISList.GetHead();
  1284. if (pHead && pHead->GetItemValue().m_pStyle)
  1285. {
  1286. IUnknown* pIDMS = NULL;
  1287. hr = pHead->GetItemValue().m_pStyle->QueryInterface(IID_IUnknown, (void**)&pIDMS);
  1288. if (SUCCEEDED(hr))
  1289. {
  1290. *ppStyle = pIDMS;
  1291. pIDMS->Release();
  1292. hr = S_OK;
  1293. }
  1294. }
  1295. else
  1296. hr = E_FAIL;
  1297. LeaveCriticalSection( &m_CriticalSection );
  1298. return hr;
  1299. }
  1300. // need this for state data, not clock time
  1301. STDMETHODIMP CStyleTrack::GetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  1302. REFERENCE_TIME* prtNext,void* pParam,void * pStateData, DWORD dwFlags)
  1303. {
  1304. MUSIC_TIME mtNext = 0;
  1305. HRESULT hr = GetParam(rguidType,(MUSIC_TIME) rtTime, &mtNext, pParam, pStateData);
  1306. if (prtNext)
  1307. {
  1308. *prtNext = mtNext;
  1309. }
  1310. return hr;
  1311. }
  1312. // only needed because we needed to pass state data into GetParam
  1313. STDMETHODIMP CStyleTrack::SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  1314. void* pParam, void * pStateData, DWORD dwFlags)
  1315. {
  1316. return SetParam(rguidType, (MUSIC_TIME) rtTime , pParam);
  1317. }
  1318. // only needed because we needed to pass state data into GetParam
  1319. STDMETHODIMP CStyleTrack::PlayEx(void* pStateData,REFERENCE_TIME rtStart,
  1320. REFERENCE_TIME rtEnd,REFERENCE_TIME rtOffset,
  1321. DWORD dwFlags,IDirectMusicPerformance* pPerf,
  1322. IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID)
  1323. {
  1324. V_INAME(IDirectMusicTrack::PlayEx);
  1325. V_INTERFACE(pPerf);
  1326. V_INTERFACE(pSegSt);
  1327. HRESULT hr;
  1328. EnterCriticalSection(&m_CriticalSection);
  1329. hr = Play(pStateData, (MUSIC_TIME)rtStart, (MUSIC_TIME)rtEnd,
  1330. (MUSIC_TIME)rtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
  1331. LeaveCriticalSection(&m_CriticalSection);
  1332. return hr;
  1333. }
  1334. HRESULT CStyleTrack::GetParam(
  1335. REFGUID rCommandGuid,
  1336. MUSIC_TIME mtTime,
  1337. MUSIC_TIME* pmtNext,
  1338. void *pData)
  1339. {
  1340. return GetParam(rCommandGuid, mtTime, pmtNext, pData, NULL);
  1341. }
  1342. STDMETHODIMP CStyleTrack::Compose(
  1343. IUnknown* pContext,
  1344. DWORD dwTrackGroup,
  1345. IDirectMusicTrack** ppResultTrack)
  1346. {
  1347. return E_NOTIMPL;
  1348. }
  1349. STDMETHODIMP CStyleTrack::Join(
  1350. IDirectMusicTrack* pNewTrack,
  1351. MUSIC_TIME mtJoin,
  1352. IUnknown* pContext,
  1353. DWORD dwTrackGroup,
  1354. IDirectMusicTrack** ppResultTrack)
  1355. {
  1356. V_INAME(IDirectMusicTrack::Join);
  1357. V_INTERFACE(pNewTrack);
  1358. V_INTERFACE_OPT(pContext);
  1359. V_PTRPTR_WRITE_OPT(ppResultTrack);
  1360. HRESULT hr = S_OK;
  1361. EnterCriticalSection(&m_CriticalSection);
  1362. if (ppResultTrack)
  1363. {
  1364. hr = Clone(0, mtJoin, ppResultTrack);
  1365. if (SUCCEEDED(hr))
  1366. {
  1367. hr = ((CStyleTrack*)*ppResultTrack)->JoinInternal(pNewTrack, mtJoin, dwTrackGroup);
  1368. }
  1369. }
  1370. else
  1371. {
  1372. hr = JoinInternal(pNewTrack, mtJoin, dwTrackGroup);
  1373. }
  1374. LeaveCriticalSection(&m_CriticalSection);
  1375. return hr;
  1376. }
  1377. HRESULT CStyleTrack::JoinInternal(
  1378. IDirectMusicTrack* pNewTrack,
  1379. MUSIC_TIME mtJoin,
  1380. DWORD dwTrackGroup)
  1381. {
  1382. HRESULT hr = S_OK;
  1383. CStyleTrack* pOtherTrack = (CStyleTrack*)pNewTrack;
  1384. if (!m_pTrackInfo || !pOtherTrack->m_pTrackInfo)
  1385. {
  1386. return DMUS_E_NOT_INIT;
  1387. }
  1388. TListItem<StylePair>* pScan = pOtherTrack->m_pTrackInfo->m_pISList.GetHead();
  1389. for (; pScan; pScan = pScan->GetNext())
  1390. {
  1391. StylePair& rScan = pScan->GetItemValue();
  1392. TListItem<StylePair>* pNew = new TListItem<StylePair>;
  1393. if (pNew)
  1394. {
  1395. StylePair& rNew = pNew->GetItemValue();
  1396. rNew.m_mtTime = rScan.m_mtTime + mtJoin;
  1397. rNew.m_pStyle = rScan.m_pStyle;
  1398. if (rNew.m_pStyle) rNew.m_pStyle->AddRef();
  1399. m_pTrackInfo->m_pISList.AddTail(pNew);
  1400. }
  1401. else
  1402. {
  1403. hr = E_OUTOFMEMORY;
  1404. break;
  1405. }
  1406. }
  1407. return hr;
  1408. }