Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1130 lines
36 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1998-2001 Microsoft Corporation
  4. //
  5. // File: dmsect.cpp
  6. //
  7. //--------------------------------------------------------------------------
  8. // DMSection.cpp : Implementation of CDMSection
  9. #include "DMSect.h"
  10. #include "DMStyle.h"
  11. #include <initguid.h>
  12. #include "debug.h"
  13. #include "..\dmloader\ima.h"
  14. #include "..\shared\Validate.h"
  15. HRESULT CDMSection::GetDescriptor(LPDMUS_OBJECTDESC pDesc)
  16. {
  17. return S_OK;
  18. }
  19. HRESULT CDMSection::SetDescriptor(LPDMUS_OBJECTDESC pDesc)
  20. {
  21. return S_OK;
  22. }
  23. HRESULT CDMSection::ParseDescriptor(LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc)
  24. {
  25. return S_OK;
  26. }
  27. STDMETHODIMP CDMSection::QueryInterface(
  28. const IID &iid,
  29. void **ppv)
  30. {
  31. V_INAME(CDMSection::QueryInterface);
  32. V_REFGUID(iid);
  33. V_PTRPTR_WRITE(ppv);
  34. if (iid == IID_IUnknown || iid == IID_IDMSection)
  35. {
  36. *ppv = static_cast<IDMSection*>(this);
  37. }
  38. else if (iid == IID_IPersistStream)
  39. {
  40. *ppv = static_cast<IPersistStream*>(this);
  41. }
  42. else if (iid == IID_IDirectMusicObject)
  43. {
  44. *ppv = static_cast<IDirectMusicObject*>(this);
  45. }
  46. else
  47. {
  48. *ppv = NULL;
  49. return E_NOINTERFACE;
  50. }
  51. reinterpret_cast<IUnknown*>(this)->AddRef();
  52. return S_OK;
  53. }
  54. STDMETHODIMP_(ULONG) CDMSection::AddRef()
  55. {
  56. return InterlockedIncrement(&m_cRef);
  57. }
  58. STDMETHODIMP_(ULONG) CDMSection::Release()
  59. {
  60. if (!InterlockedDecrement(&m_cRef))
  61. {
  62. delete this;
  63. return 0;
  64. }
  65. return m_cRef;
  66. }
  67. /////////////////////////////////////////////////////////////////////////////
  68. // CDMSection
  69. STDMETHODIMP CDMSection::GetStyle(IUnknown * * ppStyle)
  70. {
  71. HRESULT hr;
  72. if (m_pStyle)
  73. {
  74. IUnknown* pIU = NULL;
  75. hr = m_pStyle->QueryInterface(IID_IUnknown, (void**)&pIU);
  76. if (SUCCEEDED(hr))
  77. {
  78. *ppStyle = pIU;
  79. pIU->Release();
  80. hr = S_OK;
  81. }
  82. }
  83. else
  84. hr = E_FAIL;
  85. return hr;
  86. }
  87. STDMETHODIMP CDMSection::CreateSegment(IDirectMusicSegment* pISegment)
  88. {
  89. HRESULT hr = S_OK;
  90. IDirectMusicTrack* pIStyleTrack = NULL;
  91. IDirectMusicTrack* pICommandTrack = NULL;
  92. IDirectMusicTrack* pIChordTrack = NULL;
  93. IDirectMusicTrack* pBandTrack = NULL;
  94. IDirectMusicTrack* pDMTrack = NULL;
  95. IAARIFFStream* pCommandRIFF = NULL;
  96. IAARIFFStream* pChordRIFF = NULL;
  97. IStream* pICommandStream = NULL;
  98. IStream* pIChordStream = NULL;
  99. IPersistStream* pICommandTrackStream = NULL;
  100. IPersistStream* pIChordTrackStream = NULL;
  101. IStyleTrack* pS = NULL;
  102. IUnknown* pU = NULL;
  103. DMUS_BAND_PARAM DMBandParam;
  104. // 1. Create Style, Command, and Chord Tracks.
  105. hr = ::CoCreateInstance(
  106. CLSID_DirectMusicStyleTrack,
  107. NULL,
  108. CLSCTX_INPROC,
  109. IID_IDirectMusicTrack,
  110. (void**)&pIStyleTrack
  111. );
  112. if (FAILED(hr)) goto ON_END;
  113. hr = ::CoCreateInstance(
  114. CLSID_DirectMusicCommandTrack,
  115. NULL,
  116. CLSCTX_INPROC,
  117. IID_IDirectMusicTrack,
  118. (void**)&pICommandTrack
  119. );
  120. if (FAILED(hr)) goto ON_END;
  121. hr = ::CoCreateInstance(
  122. CLSID_DirectMusicChordTrack,
  123. NULL,
  124. CLSCTX_INPROC,
  125. IID_IDirectMusicTrack,
  126. (void**)&pIChordTrack
  127. );
  128. if (FAILED(hr)) goto ON_END;
  129. hr = ::CoCreateInstance(
  130. CLSID_DirectMusicBandTrack,
  131. NULL,
  132. CLSCTX_INPROC,
  133. IID_IDirectMusicTrack,
  134. (void**)&pBandTrack
  135. );
  136. if (FAILED(hr)) goto ON_END;
  137. // 2/3. Use the section's style create a style track.
  138. hr = m_pStyle->QueryInterface(IID_IUnknown, (void**)&pU);
  139. if (FAILED(hr)) goto ON_END;
  140. hr = pIStyleTrack->QueryInterface(IID_IStyleTrack, (void**)&pS);
  141. if (FAILED(hr)) goto ON_END;
  142. pS->SetTrack(pU);
  143. m_pStyle->AddRef(); // Whenever I create a track from a style, I need to addref the style
  144. // 4. Write the section's command list out to a stream.
  145. hr = CreateStreamOnHGlobal(NULL, TRUE, &pICommandStream);
  146. if (FAILED(hr)) goto ON_END;
  147. hr = AllocRIFFStream( pICommandStream, &pCommandRIFF);
  148. if (FAILED(hr)) goto ON_END;
  149. SaveCommandList(pCommandRIFF);
  150. // 5. Write the section's chord list out to a stream.
  151. hr = CreateStreamOnHGlobal(NULL, TRUE, &pIChordStream);
  152. if (S_OK != hr) goto ON_END;
  153. hr = AllocRIFFStream( pIChordStream, &pChordRIFF);
  154. if (FAILED(hr)) goto ON_END;
  155. SaveChordList(pChordRIFF);
  156. // 6. Use the command list stream as input to the Command Track's Load method.
  157. hr = pICommandTrack->QueryInterface(IID_IPersistStream, (void**)&pICommandTrackStream);
  158. if (FAILED(hr)) goto ON_END;
  159. StreamSeek(pICommandStream, 0, STREAM_SEEK_SET);
  160. hr = pICommandTrackStream->Load(pICommandStream);
  161. if (FAILED(hr)) goto ON_END;
  162. // 7a. Use the chord list stream as input to the Chord Track's Load method.
  163. hr = pIChordTrack->QueryInterface(IID_IPersistStream, (void**)&pIChordTrackStream);
  164. if (FAILED(hr)) goto ON_END;
  165. StreamSeek(pIChordStream, 0, STREAM_SEEK_SET);
  166. hr = pIChordTrackStream->Load(pIChordStream);
  167. if(FAILED(hr)) goto ON_END;
  168. // 7b. Load band into band track
  169. DMBandParam.mtTimePhysical = -64;
  170. DMBandParam.pBand = m_pIDMBand;
  171. hr = pBandTrack->SetParam(GUID_BandParam, 0, (void*)&DMBandParam);
  172. if (FAILED(hr)) goto ON_END;
  173. // 8. Create a Segment has been removed it is now passed in
  174. // 9. Initialize the segment appropriately.
  175. pISegment->SetRepeats(m_wRepeats);
  176. pISegment->SetDefaultResolution((DWORD)m_wClocksPerBeat);
  177. pISegment->SetLength(m_dwClockLength); // need the length of the section!
  178. /////////////////////////////////////////////////////////////////
  179. DMUS_TEMPO_PARAM tempo;
  180. tempo.mtTime = 0; // ConvertTime( dwTime );
  181. tempo.dblTempo = (double) m_wTempo; // ((double)dw) / 64;
  182. /////////////////////////////////////////////////////////////////
  183. hr = S_OK;
  184. // Create a Tempo Track in which to store the tempo events
  185. if( SUCCEEDED( CoCreateInstance( CLSID_DirectMusicTempoTrack,
  186. NULL, CLSCTX_INPROC, IID_IDirectMusicTrack,
  187. (void**)&pDMTrack )))
  188. {
  189. GUID Guid = GUID_TempoParam;
  190. if ( SUCCEEDED(pDMTrack->SetParam(Guid, 0, &tempo)))
  191. {
  192. pISegment->InsertTrack( pDMTrack, 1 );
  193. }
  194. }
  195. // 10. Insert the three Tracks into the Segment's Track list.
  196. pISegment->InsertTrack(pBandTrack, 1);
  197. pISegment->InsertTrack(pIStyleTrack, 1);
  198. pISegment->InsertTrack(pICommandTrack, 1);
  199. pISegment->InsertTrack(pIChordTrack, 1);
  200. // Note: the segment must release the track objects...
  201. ON_END:
  202. if (pDMTrack) pDMTrack->Release();
  203. if (pIChordStream) pIChordStream->Release();
  204. if (pIChordTrackStream) pIChordTrackStream->Release();
  205. if (pICommandStream) pICommandStream->Release();
  206. if (pICommandTrackStream) pICommandTrackStream->Release();
  207. if (pCommandRIFF) pCommandRIFF->Release();
  208. if (pChordRIFF) pChordRIFF->Release();
  209. if (pS) pS->Release();
  210. if (pU) pU->Release();
  211. if (pIStyleTrack) pIStyleTrack->Release();
  212. if (pICommandTrack) pICommandTrack->Release();
  213. if (pIChordTrack) pIChordTrack->Release();
  214. if (pBandTrack) pBandTrack->Release();
  215. return hr;
  216. }
  217. CDMSection::CDMSection() : m_pStyle(NULL), m_pIDMBand(NULL), m_cRef(1)
  218. {
  219. InterlockedIncrement(&g_cComponent);
  220. }
  221. CDMSection::~CDMSection()
  222. {
  223. CleanUp();
  224. InterlockedDecrement(&g_cComponent);
  225. }
  226. void CDMSection::CleanUp( BOOL fStop)
  227. {
  228. if(m_pIDMBand)
  229. {
  230. m_pIDMBand->Release();
  231. }
  232. // let whoever used the section release the style.
  233. if (m_pStyle)
  234. {
  235. m_pStyle->Release();
  236. }
  237. }
  238. static BYTE setchordbits( long lPattern )
  239. {
  240. LONG i;
  241. short count = 0;
  242. BYTE bBits = 0;
  243. for( i=0L ; i<32L ; i++ )
  244. {
  245. if( lPattern & (1L << i) )
  246. count++;
  247. }
  248. bBits |= CHORD_INVERT;
  249. if( count > 3 )
  250. bBits |= CHORD_FOUR;
  251. if( lPattern & (15L << 18L) )
  252. bBits |= CHORD_UPPER;
  253. bBits &= ~CHORD_COUNT;
  254. bBits |= count;
  255. return bBits;
  256. }
  257. HRESULT CDMSection::LoadChordList( LPSTREAM pStream, LPMMCKINFO pck, TList<DMChord>& ChordList )
  258. {
  259. HRESULT hr = S_OK;
  260. DWORD cb;
  261. long lSize;
  262. TListItem<DMChord>* pChord;
  263. ioChordSelection iChordSelection;
  264. WORD wSizeChord;
  265. lSize = pck->cksize;
  266. // load size of chord structure
  267. hr = pStream->Read( &wSizeChord, sizeof( wSizeChord ), &cb );
  268. if( FAILED( hr ) || cb != sizeof( wSizeChord ) )
  269. {
  270. hr = E_FAIL;
  271. goto ON_ERR;
  272. }
  273. FixBytes( FBT_SHORT, &wSizeChord );
  274. lSize -= cb;
  275. while( lSize > 0 )
  276. {
  277. pChord = new TListItem<DMChord>;
  278. if( pChord == NULL )
  279. {
  280. hr = E_OUTOFMEMORY;
  281. goto ON_ERR;
  282. }
  283. if( wSizeChord > sizeof( ioChordSelection ) )
  284. {
  285. hr = pStream->Read( &iChordSelection, sizeof( ioChordSelection ), &cb );
  286. if( FAILED( hr ) || cb != sizeof( ioChordSelection ) )
  287. {
  288. hr = E_FAIL;
  289. goto ON_ERR;
  290. }
  291. FixBytes( FBT_IOCHORDSELECTION, &iChordSelection );
  292. StreamSeek( pStream, wSizeChord - sizeof( ioChordSelection ), STREAM_SEEK_CUR );
  293. }
  294. else
  295. {
  296. hr = pStream->Read( &iChordSelection, wSizeChord, &cb );
  297. if( FAILED( hr ) || cb != wSizeChord )
  298. {
  299. hr = E_FAIL;
  300. goto ON_ERR;
  301. }
  302. FixBytes( FBT_IOCHORDSELECTION, &iChordSelection );
  303. }
  304. lSize -= wSizeChord;
  305. // WideCharToMultiByte( CP_ACP, 0, iChordSelection.wstrName, -1, pChord->name, sizeof( pChord->name ), NULL, NULL );
  306. DMChord& rChord = pChord->GetItemValue();
  307. rChord.m_bKey = m_bRoot;
  308. rChord.m_dwScale = DEFAULT_SCALE_PATTERN;
  309. rChord.m_strName = iChordSelection.wstrName;
  310. rChord.m_bBeat = iChordSelection.bBeat;
  311. rChord.m_wMeasure = iChordSelection.wMeasure;
  312. rChord.m_mtTime = m_wClocksPerMeasure * rChord.m_wMeasure + m_wClocksPerBeat * rChord.m_bBeat;
  313. // If chordpattern contains <= n notes (for an n-note chord)
  314. // create a single subchord
  315. // Else
  316. // create 2 subchords, with the 1st having the lower n notes and the
  317. // 2nd having the upper n notes (assumes there are <= 2n notes)
  318. BYTE bBits = setchordbits( iChordSelection.aChord[0].lChordPattern );
  319. short nChordCount = bBits & CHORD_COUNT;
  320. // The root of the lower chord is the input chord's root,
  321. // relative to the scale (section) root.
  322. BYTE bChordRoot = iChordSelection.aChord[0].bRoot;
  323. // (bBits & CHORD_UPPER) ? (iChordSelection.aChord[0].bRoot - 12) : iChordSelection.aChord[0].bRoot;
  324. bChordRoot -= m_bRoot;
  325. if (bChordRoot < 0) bChordRoot += 12;
  326. if ((bBits & CHORD_FOUR && nChordCount <= 4) ||
  327. (!(bBits & CHORD_FOUR) && nChordCount <= 3))
  328. {
  329. // single subchord with all info from input chord
  330. TListItem<DMSubChord>* pSubChord = new TListItem<DMSubChord>;
  331. if( pSubChord == NULL )
  332. {
  333. hr = E_OUTOFMEMORY;
  334. goto ON_ERR;
  335. }
  336. DMSubChord& rSubChord = pSubChord->GetItemValue();
  337. if (iChordSelection.aChord[0].lChordPattern)
  338. {
  339. rSubChord.m_dwChordPattern = iChordSelection.aChord[0].lChordPattern;
  340. }
  341. else
  342. {
  343. }
  344. rSubChord.m_dwScalePattern = iChordSelection.aChord[0].lScalePattern;
  345. rSubChord.m_dwInversionPoints = 0xffffff; // default: inversions everywhere
  346. rSubChord.m_dwLevels = (1 << SUBCHORD_BASS) | (1 << SUBCHORD_STANDARD_CHORD);
  347. rSubChord.m_bChordRoot = bChordRoot;
  348. rSubChord.m_bScaleRoot = m_bRoot; // scale root is root of the section
  349. rChord.m_SubChordList.AddTail(pSubChord);
  350. }
  351. else
  352. {
  353. // two subchords both with scale and roots from input chord, and:
  354. // 1st chord: chord pattern from lower n notes of input chord
  355. // 2nd chord: chord pattern from upper n notes of input chord
  356. DWORD dwLowerSubChord = 0L;
  357. DWORD dwUpperSubChord = 0L;
  358. BYTE bUpperRoot = bChordRoot;
  359. DWORD dwChordPattern = iChordSelection.aChord[0].lChordPattern;
  360. short nIgnoreHigh = (bBits & CHORD_FOUR) ? 4 : 3;
  361. short nIgnoreLow = (bBits & CHORD_FOUR) ? nChordCount - 4 : nChordCount - 3;
  362. short nLowestUpper = 0;
  363. for (short nPos = 0, nCount = 0; nPos < 24; nPos++)
  364. {
  365. if (dwChordPattern & 1)
  366. {
  367. if (nCount < nIgnoreHigh)
  368. {
  369. dwLowerSubChord |= 1L << nPos;
  370. }
  371. if (nCount >= nIgnoreLow)
  372. {
  373. if (!nLowestUpper)
  374. {
  375. nLowestUpper = nPos;
  376. bUpperRoot = (bUpperRoot + (BYTE) nLowestUpper);
  377. }
  378. dwUpperSubChord |= 1L << (nPos - nLowestUpper);
  379. }
  380. nCount++;
  381. if (nCount >= nChordCount)
  382. break;
  383. }
  384. dwChordPattern >>= 1L;
  385. }
  386. // now, create the two subchords.
  387. TListItem<DMSubChord>* pLowerSubChord = new TListItem<DMSubChord>;
  388. if( pLowerSubChord == NULL )
  389. {
  390. hr = E_OUTOFMEMORY;
  391. goto ON_ERR;
  392. }
  393. DMSubChord& rLowerSubChord = pLowerSubChord->GetItemValue();
  394. rLowerSubChord.m_dwChordPattern = dwLowerSubChord;
  395. rLowerSubChord.m_dwScalePattern = iChordSelection.aChord[0].lScalePattern;
  396. rLowerSubChord.m_dwInversionPoints = 0xffffff; // default: inversions everywhere
  397. rLowerSubChord.m_dwLevels = (1 << SUBCHORD_BASS);
  398. rLowerSubChord.m_bChordRoot = bChordRoot;
  399. rLowerSubChord.m_bScaleRoot = m_bRoot; // scale root is root of the section
  400. rChord.m_SubChordList.AddTail(pLowerSubChord);
  401. TListItem<DMSubChord>* pUpperSubChord = new TListItem<DMSubChord>;
  402. if( pUpperSubChord == NULL )
  403. {
  404. hr = E_OUTOFMEMORY;
  405. goto ON_ERR;
  406. }
  407. DMSubChord& rUpperSubChord = pUpperSubChord->GetItemValue();
  408. rUpperSubChord.m_dwChordPattern = dwUpperSubChord;
  409. rUpperSubChord.m_dwScalePattern = iChordSelection.aChord[0].lScalePattern;
  410. rUpperSubChord.m_dwInversionPoints = 0xffffff; // default: inversions everywhere
  411. rUpperSubChord.m_dwLevels = (1 << SUBCHORD_STANDARD_CHORD);
  412. rUpperSubChord.m_bChordRoot = bUpperRoot % 24;
  413. while (rUpperSubChord.m_bChordRoot < rLowerSubChord.m_bChordRoot)
  414. rUpperSubChord.m_bChordRoot += 12;
  415. rUpperSubChord.m_bScaleRoot = m_bRoot; // scale root is root of the section
  416. rChord.m_SubChordList.AddTail(pUpperSubChord);
  417. }
  418. ChordList.AddTail(pChord);
  419. }
  420. ON_ERR:
  421. return hr;
  422. }
  423. HRESULT CDMSection::LoadCommandList( LPSTREAM pStream, LPMMCKINFO pck, TList<DMCommand>& CommandList )
  424. {
  425. HRESULT hr = S_OK;
  426. DWORD cb;
  427. long lSize;
  428. TListItem<DMCommand>* pCommand;
  429. ioCommand iCommand;
  430. WORD wSizeCommand;
  431. lSize = pck->cksize;
  432. // load size of command structure
  433. hr = pStream->Read( &wSizeCommand, sizeof( wSizeCommand ), &cb );
  434. if( FAILED( hr ) || cb != sizeof( wSizeCommand ) )
  435. {
  436. hr = E_FAIL;
  437. goto ON_ERR;
  438. }
  439. FixBytes( FBT_SHORT, &wSizeCommand );
  440. lSize -= cb;
  441. while( lSize > 0 )
  442. {
  443. pCommand = new TListItem<DMCommand>;
  444. if( pCommand == NULL )
  445. {
  446. hr = E_OUTOFMEMORY;
  447. goto ON_ERR;
  448. }
  449. if( wSizeCommand > sizeof( ioCommand ) )
  450. {
  451. hr = pStream->Read( &iCommand, sizeof( ioCommand ), &cb );
  452. if( FAILED( hr ) || cb != sizeof( ioCommand ) )
  453. {
  454. hr = E_FAIL;
  455. goto ON_ERR;
  456. }
  457. FixBytes( FBT_IOCOMMAND, &iCommand );
  458. StreamSeek( pStream, wSizeCommand - sizeof( ioCommand ), STREAM_SEEK_CUR );
  459. }
  460. else
  461. {
  462. hr = pStream->Read( &iCommand, wSizeCommand, &cb );
  463. if( FAILED( hr ) || cb != wSizeCommand )
  464. {
  465. hr = E_FAIL;
  466. goto ON_ERR;
  467. }
  468. FixBytes( FBT_IOCOMMAND, &iCommand );
  469. }
  470. lSize -= wSizeCommand;
  471. DMCommand& rCommand = pCommand->GetItemValue();
  472. ////////////////////////////////////////////////////////////////////
  473. // Change this from absolute time to measures and beats!
  474. ////////////////////////////////////////////////////////////////////
  475. // To convert clock time to measures and beats:
  476. // 1. Use clocksPerMeasure to find the measure
  477. // 2. Use clocksPerBeat to find the beat
  478. // DWORD dwClocks = rCommand.m_dwTime - m_dwTime;
  479. rCommand.m_wMeasure = (WORD) (ConvertTime(iCommand.lTime) / m_wClocksPerMeasure); // assumes 1st measure is 0
  480. rCommand.m_bBeat = (BYTE) ((ConvertTime(iCommand.lTime) % m_wClocksPerMeasure) / m_wClocksPerBeat); // ditto
  481. rCommand.m_mtTime = ConvertTime(iCommand.lTime);
  482. /////////////////////////////////////////////////////////////////////
  483. switch (iCommand.dwCommand & PF_RIFF)
  484. {
  485. case PF_INTRO:
  486. rCommand.m_bCommand = DMUS_COMMANDT_INTRO;
  487. break;
  488. case PF_END:
  489. rCommand.m_bCommand = DMUS_COMMANDT_END;
  490. break;
  491. case PF_BREAK:
  492. rCommand.m_bCommand = DMUS_COMMANDT_BREAK;
  493. break;
  494. case PF_FILL:
  495. rCommand.m_bCommand = DMUS_COMMANDT_FILL;
  496. break;
  497. default:
  498. rCommand.m_bCommand = DMUS_COMMANDT_GROOVE;
  499. }
  500. switch (iCommand.dwCommand & PF_GROOVE)
  501. {
  502. case PF_A:
  503. rCommand.m_bGrooveLevel = 12;
  504. break;
  505. case PF_B:
  506. rCommand.m_bGrooveLevel = 37;
  507. break;
  508. case PF_C:
  509. rCommand.m_bGrooveLevel = 62;
  510. break;
  511. case PF_D:
  512. rCommand.m_bGrooveLevel = 87;
  513. break;
  514. default:
  515. rCommand.m_bGrooveLevel = 0;
  516. }
  517. rCommand.m_bGrooveRange = 0;
  518. rCommand.m_bRepeatMode = DMUS_PATTERNT_RANDOM;
  519. CommandList.AddTail(pCommand);
  520. }
  521. ON_ERR:
  522. return hr;
  523. }
  524. HRESULT CDMSection::LoadStyleReference( LPSTREAM pStream, MMCKINFO* pck)
  525. {
  526. HRESULT hr;
  527. DWORD cb;
  528. DWORD cSize;
  529. //char szName[40];
  530. wchar_t wstrName[40];
  531. //IAALoader* pLoader;
  532. cSize = min( pck->cksize, sizeof( wstrName ) );
  533. hr = pStream->Read( wstrName, cSize, &cb );
  534. if( FAILED( hr ) || cb != cSize )
  535. {
  536. return E_FAIL;
  537. }
  538. m_strStyleName = wstrName;
  539. DMUS_OBJECTDESC ObjectDescript;
  540. ObjectDescript.dwSize = sizeof(DMUS_OBJECTDESC);
  541. ObjectDescript.guidClass = CLSID_DirectMusicStyle;
  542. wcscpy(ObjectDescript.wszName, wstrName);
  543. ObjectDescript.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_NAME;
  544. IDirectMusicLoader* pLoader;
  545. IDirectMusicGetLoader *pIGetLoader; // <==============
  546. hr = pStream->QueryInterface( IID_IDirectMusicGetLoader, (void **) &pIGetLoader );// <========
  547. if (SUCCEEDED(hr))
  548. {
  549. hr = pIGetLoader->GetLoader(&pLoader); // <========
  550. if (SUCCEEDED(hr)) // <========
  551. { // <========
  552. hr = pLoader->GetObject(&ObjectDescript, IID_IDirectMusicStyle, (void**)&m_pStyle);
  553. pLoader->Release();
  554. } // <========
  555. pIGetLoader->Release(); // <========
  556. }
  557. return hr;
  558. }
  559. HRESULT CDMSection::LoadSection( IAARIFFStream* pRIFF, MMCKINFO* pckMain )
  560. {
  561. HRESULT hr = S_OK;
  562. HRESULT hrBand = S_OK;
  563. ioSection iSection;
  564. MMCKINFO ck;
  565. DWORD cb;
  566. DWORD cSize;
  567. IStream* pStream;
  568. BOOL fLoadedSection = FALSE;
  569. pStream = pRIFF->GetStream();
  570. while( pRIFF->Descend( &ck, pckMain, 0 ) == 0 )
  571. {
  572. switch( ck.ckid )
  573. {
  574. case FOURCC_SECTION:
  575. cSize = min( ck.cksize, sizeof( iSection ) );
  576. hr = pStream->Read( &iSection, cSize, &cb );
  577. if( FAILED( hr ) || cb != cSize )
  578. {
  579. hr = E_FAIL;
  580. goto ON_ERR;
  581. }
  582. FixBytes( FBT_IOSECTION, &iSection );
  583. m_strName = iSection.wstrName;
  584. m_dwTime = iSection.lTime;
  585. m_wTempo = iSection.wTempo;
  586. // wRepeats refers to repeats after the first play.
  587. m_wRepeats = iSection.wRepeats;
  588. m_wMeasureLength = iSection.wMeasureLength;
  589. m_wClocksPerMeasure = ConvertTime(iSection.wClocksPerMeasure);
  590. m_wClocksPerBeat = ConvertTime(iSection.wClocksPerBeat);
  591. m_wTempoFract = iSection.wTempoFract;
  592. m_dwFlags = iSection.dwFlags;
  593. m_bRoot = (char)( iSection.chKey & ~KEY_FLAT );
  594. m_dwClockLength = (long)m_wMeasureLength * (long)m_wClocksPerMeasure;
  595. fLoadedSection = TRUE;
  596. break;
  597. case FOURCC_STYLEREF:
  598. if( fLoadedSection )
  599. {
  600. hr = LoadStyleReference( pStream, &ck );
  601. if (hr != S_OK)
  602. {
  603. hrBand = hr;
  604. }
  605. if( FAILED( hr ) )
  606. {
  607. goto ON_ERR;
  608. }
  609. }
  610. break;
  611. case FOURCC_RIFF:
  612. switch(ck.fccType)
  613. {
  614. case FOURCC_BAND_FORM:
  615. {
  616. // Create a band
  617. hr = CoCreateInstance(CLSID_DirectMusicBand,
  618. NULL,
  619. CLSCTX_INPROC,
  620. IID_IDirectMusicBand,
  621. (void**)&m_pIDMBand);
  622. if(SUCCEEDED(hr))
  623. {
  624. // Seek back to begining of Riff chunk
  625. // This is the amount read by Descend when descending into a FOURCC_RIFF chunk
  626. // Get current position
  627. LARGE_INTEGER li;
  628. ULARGE_INTEGER ul;
  629. li.HighPart = 0;
  630. li.LowPart = 0;
  631. hr = pStream->Seek(li,
  632. STREAM_SEEK_CUR,
  633. &ul);
  634. if(SUCCEEDED(hr))
  635. {
  636. li.HighPart = 0;
  637. // This is always a valid operation
  638. li.LowPart = ul.LowPart - (2 * sizeof(FOURCC) + sizeof(DWORD));
  639. hr = pStream->Seek(li,
  640. STREAM_SEEK_SET,
  641. &ul);
  642. }
  643. }
  644. if(SUCCEEDED(hr))
  645. {
  646. // Load band
  647. IPersistStream* pIPersistStream;
  648. hr = m_pIDMBand->QueryInterface(IID_IPersistStream, (void **)&pIPersistStream);
  649. if(SUCCEEDED(hr))
  650. {
  651. hr = pIPersistStream->Load(pStream);
  652. if (hr != S_OK)
  653. {
  654. hrBand = hr;
  655. }
  656. pIPersistStream->Release();
  657. }
  658. }
  659. if(FAILED(hr))
  660. {
  661. goto ON_ERR;
  662. }
  663. }
  664. break;
  665. }
  666. break;
  667. case FOURCC_CHORD:
  668. if( fLoadedSection )
  669. {
  670. hr = LoadChordList( pStream, &ck, m_ChordList );
  671. if( FAILED( hr ) )
  672. {
  673. goto ON_ERR;
  674. }
  675. }
  676. break;
  677. case FOURCC_COMMAND:
  678. if( fLoadedSection )
  679. {
  680. hr = LoadCommandList( pStream, &ck, m_CommandList );
  681. if( FAILED( hr ) )
  682. {
  683. goto ON_ERR;
  684. }
  685. }
  686. break;
  687. }
  688. pRIFF->Ascend( &ck, 0 );
  689. }
  690. ON_ERR:
  691. if( FAILED( hr ) )
  692. {
  693. if(m_pIDMBand != NULL)
  694. {
  695. if(m_pIDMBand)
  696. {
  697. m_pIDMBand->Release();
  698. }
  699. m_pIDMBand = NULL;
  700. }
  701. }
  702. pStream->Release( );
  703. if (hr == S_OK && hrBand != S_OK)
  704. {
  705. hr = hrBand;
  706. }
  707. return hr;
  708. }
  709. HRESULT CDMSection::Load(
  710. LPSTREAM pStream ) // Pointer to a stream that contains the
  711. // Section information to load.
  712. {
  713. DWORD dwPos;
  714. IAARIFFStream* pRIFF;
  715. MMCKINFO ckMain;
  716. HRESULT hr;
  717. if ( pStream == NULL ) return E_INVALIDARG;
  718. hr = E_FAIL;
  719. CleanUp( FALSE );
  720. dwPos = StreamTell( pStream );
  721. StreamSeek( pStream, dwPos, STREAM_SEEK_SET );
  722. if( SUCCEEDED( AllocRIFFStream( pStream, &pRIFF ) ) )
  723. {
  724. ckMain.fccType = FOURCC_SECTION_FORM;
  725. if( pRIFF->Descend( &ckMain, NULL, MMIO_FINDRIFF ) == 0 )
  726. {
  727. hr = LoadSection( pRIFF, &ckMain );
  728. pRIFF->Ascend( &ckMain, 0 );
  729. }
  730. pRIFF->Release( );
  731. }
  732. return hr;
  733. }
  734. DMChord::DMChord(DMUS_CHORD_PARAM& DMC)
  735. {
  736. m_strName = DMC.wszName;
  737. m_wMeasure = DMC.wMeasure;
  738. m_bBeat = DMC.bBeat;
  739. m_bKey = DMC.bKey;
  740. m_dwScale = DMC.dwScale;
  741. m_fSilent = (DMC.bFlags & DMUS_CHORDKEYF_SILENT) ? true : false;
  742. for (BYTE n = 0; n < DMC.bSubChordCount; n++)
  743. {
  744. TListItem<DMSubChord>* pSub = new TListItem<DMSubChord>(DMC.SubChordList[n]);
  745. if (pSub)
  746. {
  747. m_SubChordList.AddTail(pSub);
  748. }
  749. }
  750. }
  751. DMChord::DMChord(DMChord& DMC)
  752. {
  753. m_strName = DMC.m_strName;
  754. m_wMeasure = DMC.m_wMeasure;
  755. m_bBeat = DMC.m_bBeat;
  756. m_bKey = DMC.m_bKey;
  757. m_dwScale = DMC.m_dwScale;
  758. m_fSilent = DMC.m_fSilent;
  759. TListItem<DMSubChord>* pScan = DMC.m_SubChordList.GetHead();
  760. for (; pScan != NULL; pScan = pScan->GetNext())
  761. {
  762. TListItem<DMSubChord>* pSub = new TListItem<DMSubChord>(pScan->GetItemValue());
  763. if (pSub)
  764. {
  765. m_SubChordList.AddTail(pSub);
  766. }
  767. }
  768. }
  769. DMChord& DMChord::operator=(const DMChord& DMC)
  770. {
  771. if (this != &DMC)
  772. {
  773. m_strName = DMC.m_strName;
  774. m_wMeasure = DMC.m_wMeasure;
  775. m_bBeat = DMC.m_bBeat;
  776. m_bKey = DMC.m_bKey;
  777. m_dwScale = DMC.m_dwScale;
  778. m_fSilent = DMC.m_fSilent;
  779. m_SubChordList.CleanUp();
  780. TListItem<DMSubChord>* pScan = DMC.m_SubChordList.GetHead();
  781. for (; pScan != NULL; pScan = pScan->GetNext())
  782. {
  783. TListItem<DMSubChord>* pSub = new TListItem<DMSubChord>(pScan->GetItemValue());
  784. if (pSub)
  785. {
  786. m_SubChordList.AddTail(pSub);
  787. }
  788. }
  789. }
  790. return *this;
  791. }
  792. DMChord::operator DMUS_CHORD_PARAM()
  793. {
  794. DMUS_CHORD_PARAM result;
  795. wcscpy(result.wszName, m_strName);
  796. result.wMeasure = m_wMeasure;
  797. result.bBeat = m_bBeat;
  798. result.bKey = m_bKey;
  799. result.dwScale = m_dwScale;
  800. result.bFlags = 0;
  801. if (m_fSilent) result.bFlags |= DMUS_CHORDKEYF_SILENT;
  802. BYTE n = 0;
  803. TListItem<DMSubChord>* pSub = m_SubChordList.GetHead();
  804. for (; pSub != NULL; pSub = pSub->GetNext(), n++)
  805. {
  806. result.SubChordList[n] = pSub->GetItemValue();
  807. }
  808. result.bSubChordCount = n;
  809. return result;
  810. }
  811. HRESULT DMChord::Save( IAARIFFStream* pRIFF )
  812. {
  813. IStream* pStream;
  814. MMCKINFO ck;
  815. DWORD cb;
  816. DMUS_IO_CHORD iChord;
  817. DMUS_IO_SUBCHORD iSubChord;
  818. DWORD dwSize;
  819. HRESULT hr = E_FAIL;
  820. pStream = pRIFF->GetStream();
  821. ck.ckid = mmioFOURCC('c', 'r', 'd', 'b');
  822. if( pRIFF->CreateChunk( &ck, 0 ) == 0 )
  823. {
  824. memset( &iChord, 0, sizeof( iChord ) );
  825. m_strName = iChord.wszName;
  826. //MultiByteToWideChar( CP_ACP, 0, m_strName, -1, iChord.wszName, sizeof( iChord.wszName ) / sizeof( wchar_t ) );
  827. iChord.mtTime = m_mtTime;
  828. iChord.wMeasure = m_wMeasure;
  829. iChord.bBeat = m_bBeat;
  830. iChord.bFlags = 0;
  831. if (m_fSilent) iChord.bFlags |= DMUS_CHORDKEYF_SILENT;
  832. dwSize = sizeof( iChord );
  833. hr = pStream->Write( &dwSize, sizeof( dwSize ), &cb );
  834. if( SUCCEEDED(hr) &&
  835. SUCCEEDED( pStream->Write( &iChord, sizeof( iChord), &cb ) ) &&
  836. cb == sizeof( iChord) ) // &&
  837. //pRIFF->Ascend( &ck, 0 ) == 0 )
  838. {
  839. //ck.ckid = mmioFOURCC('s', 'u', 'b', 'c');
  840. //if( pRIFF->CreateChunk( &ck, 0 ) == 0 )
  841. {
  842. DWORD dwCount = (WORD) m_SubChordList.GetCount();
  843. hr = pStream->Write( &dwCount, sizeof( dwCount ), &cb );
  844. if( FAILED( hr ) || cb != sizeof( dwSize ) )
  845. {
  846. pStream->Release();
  847. return E_FAIL;
  848. }
  849. dwSize = sizeof( iSubChord );
  850. hr = pStream->Write( &dwSize, sizeof( dwSize ), &cb );
  851. if( FAILED( hr ) || cb != sizeof( dwSize ) )
  852. {
  853. pStream->Release();
  854. return E_FAIL;
  855. }
  856. for (TListItem<DMSubChord>* pSub = m_SubChordList.GetHead(); pSub != NULL; pSub = pSub->GetNext())
  857. {
  858. DMSubChord& rSubChord = pSub->GetItemValue();
  859. memset( &iSubChord, 0, sizeof( iSubChord ) );
  860. iSubChord.dwChordPattern = rSubChord.m_dwChordPattern;
  861. iSubChord.dwScalePattern = rSubChord.m_dwScalePattern;
  862. iSubChord.dwInversionPoints = rSubChord.m_dwInversionPoints;
  863. iSubChord.dwLevels = rSubChord.m_dwLevels;
  864. iSubChord.bChordRoot = rSubChord.m_bChordRoot;
  865. iSubChord.bScaleRoot = rSubChord.m_bScaleRoot;
  866. if( FAILED( pStream->Write( &iSubChord, sizeof( iSubChord ), &cb ) ) ||
  867. cb != sizeof( iSubChord ) )
  868. {
  869. break;
  870. }
  871. }
  872. // ascend from chord body chunk
  873. if( pSub == NULL &&
  874. pRIFF->Ascend( &ck, 0 ) != 0 )
  875. {
  876. hr = S_OK;
  877. }
  878. }
  879. }
  880. }
  881. pStream->Release();
  882. return hr;
  883. }
  884. HRESULT CDMSection::SaveChordList( IAARIFFStream* pRIFF )
  885. {
  886. IStream* pStream;
  887. //LPSECT pSection;
  888. MMCKINFO ck;
  889. MMCKINFO ckHeader;
  890. HRESULT hr;
  891. DWORD cb;
  892. //WORD wSize;
  893. TListItem<DMChord>* pChord;
  894. //int i;
  895. pStream = pRIFF->GetStream();
  896. //pSection = (LPSECT)m_pSection->lpDLL1;
  897. ck.fccType = DMUS_FOURCC_CHORDTRACK_LIST;
  898. hr = pRIFF->CreateChunk(&ck, MMIO_CREATELIST);
  899. if (SUCCEEDED(hr))
  900. {
  901. // wSize = sizeof( ioChordSelection );
  902. //FixBytes( FBT_SHORT, &wSize );
  903. // hr = pStream->Write( &wSize, sizeof( wSize ), &cb );
  904. // if( FAILED( hr ) || cb != sizeof( wSize ) )
  905. // {
  906. // RELEASE( pStream );
  907. // return E_FAIL;
  908. //}
  909. DWORD dwRoot = m_bRoot;
  910. DWORD dwScale = DEFAULT_SCALE_PATTERN | (dwRoot << 24);
  911. ckHeader.ckid = DMUS_FOURCC_CHORDTRACKHEADER_CHUNK;
  912. hr = pRIFF->CreateChunk(&ckHeader, 0);
  913. if (FAILED(hr))
  914. {
  915. pStream->Release();
  916. return hr;
  917. }
  918. hr = pStream->Write( &dwScale, sizeof( dwScale ), &cb );
  919. if (FAILED(hr))
  920. {
  921. pStream->Release();
  922. return hr;
  923. }
  924. hr = pRIFF->Ascend( &ckHeader, 0 );
  925. if (hr != S_OK)
  926. {
  927. pStream->Release();
  928. return hr;
  929. }
  930. for( pChord = m_ChordList.GetHead() ; pChord != NULL ; pChord = pChord->GetNext() )
  931. {
  932. hr = pChord->GetItemValue().Save(pRIFF);
  933. if (FAILED(hr))
  934. {
  935. pStream->Release();
  936. return hr;
  937. }
  938. }
  939. if( pChord == NULL &&
  940. pRIFF->Ascend( &ck, 0 ) == 0 )
  941. {
  942. hr = S_OK;
  943. }
  944. }
  945. pStream->Release();
  946. return hr;
  947. }
  948. HRESULT CDMSection::SaveCommandList( IAARIFFStream* pRIFF )
  949. {
  950. IStream* pStream;
  951. MMCKINFO ck;
  952. HRESULT hr;
  953. DWORD cb;
  954. DWORD dwSize;
  955. DMUS_IO_COMMAND iCommand;
  956. TListItem<DMCommand>* pCommand;
  957. pStream = pRIFF->GetStream();
  958. if (!pStream) return E_FAIL;
  959. hr = E_FAIL;
  960. ck.ckid = FOURCC_COMMAND;
  961. if( pRIFF->CreateChunk( &ck, 0 ) == 0 )
  962. {
  963. dwSize = sizeof( DMUS_IO_COMMAND );
  964. hr = pStream->Write( &dwSize, sizeof( dwSize ), &cb );
  965. if( FAILED( hr ) || cb != sizeof( dwSize ) )
  966. {
  967. pStream->Release();
  968. return E_FAIL;
  969. }
  970. for( pCommand = m_CommandList.GetHead(); pCommand != NULL ; pCommand = pCommand->GetNext() )
  971. {
  972. DMCommand& rCommand = pCommand->GetItemValue();
  973. memset( &iCommand, 0, sizeof( iCommand ) );
  974. iCommand.mtTime = rCommand.m_mtTime;
  975. iCommand.wMeasure = rCommand.m_wMeasure;
  976. iCommand.bBeat = rCommand.m_bBeat;
  977. iCommand.bCommand = rCommand.m_bCommand;
  978. iCommand.bGrooveLevel = rCommand.m_bGrooveLevel;
  979. iCommand.bGrooveRange = rCommand.m_bGrooveRange;
  980. iCommand.bRepeatMode = rCommand.m_bRepeatMode;
  981. if( FAILED( pStream->Write( &iCommand, sizeof( iCommand ), &cb ) ) ||
  982. cb != sizeof( iCommand ) )
  983. {
  984. break;
  985. }
  986. }
  987. if( pCommand == NULL &&
  988. pRIFF->Ascend( &ck, 0 ) == 0 )
  989. {
  990. hr = S_OK;
  991. }
  992. }
  993. pStream->Release();
  994. return hr;
  995. }
  996. HRESULT CDMSection::Save(
  997. LPSTREAM pStream, // Stream to store Section.
  998. BOOL /*fClearDirty*/ ) // TRUE to clear dirty flag, FALSE to leave
  999. // dirty flag unchanged.
  1000. {
  1001. IAARIFFStream* pRIFF;
  1002. HRESULT hr;
  1003. MMCKINFO ckMain;
  1004. hr = E_FAIL;
  1005. if( SUCCEEDED( AllocRIFFStream( pStream, &pRIFF ) ) )
  1006. {
  1007. ckMain.fccType = FOURCC_SECTION_FORM;
  1008. if( pRIFF->CreateChunk( &ckMain, MMIO_CREATERIFF ) != 0 )
  1009. {
  1010. goto ON_ERR;
  1011. }
  1012. if( FAILED( SaveChordList( pRIFF ) ) ||
  1013. FAILED( SaveCommandList( pRIFF ) ) )
  1014. {
  1015. goto ON_ERR;
  1016. }
  1017. if( pRIFF->Ascend( &ckMain, 0 ) != 0 )
  1018. {
  1019. goto ON_ERR;
  1020. }
  1021. hr = S_OK;
  1022. ON_ERR:
  1023. pRIFF->Release();
  1024. }
  1025. return hr;
  1026. }
  1027. /* IPersist methods */
  1028. HRESULT CDMSection::GetClassID( LPCLSID pclsid )
  1029. {
  1030. return E_NOTIMPL;
  1031. }
  1032. HRESULT CDMSection::IsDirty()
  1033. {
  1034. return E_NOTIMPL;
  1035. }
  1036. HRESULT CDMSection::GetSizeMax( ULARGE_INTEGER* /*pcbSize*/ )
  1037. {
  1038. return E_NOTIMPL;
  1039. }