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.

1480 lines
49 KiB

  1. //
  2. // DMPers.cpp : Implementation of CDMPers
  3. //
  4. // Copyright (c) 1997-2001 Microsoft Corporation
  5. //
  6. // @doc EXTERNAL
  7. //
  8. #include "DMPers.h"
  9. #include "dmusici.h"
  10. #include "..\shared\validate.h"
  11. #include "..\shared\dmscriptautguids.h"
  12. #include "debug.h"
  13. V_INAME(DMCompose)
  14. /////////////////////////////////////////////////////////////////////////////
  15. // ReadMBSfromWCS
  16. void ReadMBSfromWCS( IStream* pIStream, DWORD dwSize, String& pstrText )
  17. {
  18. HRESULT hr = S_OK;
  19. wchar_t* wstrText = NULL;
  20. DWORD dwBytesRead;
  21. pstrText = "";
  22. wstrText = new wchar_t[dwSize];
  23. if( wstrText == NULL )
  24. {
  25. hr = E_OUTOFMEMORY;
  26. goto ON_ERR;
  27. }
  28. hr = pIStream->Read( wstrText, dwSize, &dwBytesRead );
  29. if( FAILED( hr )
  30. || dwBytesRead != dwSize )
  31. {
  32. goto ON_ERR;
  33. }
  34. pstrText = wstrText;
  35. ON_ERR:
  36. if( wstrText )
  37. delete [] wstrText;
  38. }
  39. /////////// Utility functions for chords //////////////////
  40. static BYTE setchordbits( long lPattern )
  41. {
  42. LONG i;
  43. short count = 0;
  44. BYTE bBits = 0;
  45. for( i=0L ; i<32L ; i++ )
  46. {
  47. if( lPattern & (1L << i) )
  48. count++;
  49. }
  50. bBits |= CHORD_INVERT;
  51. if( count > 3 )
  52. bBits |= CHORD_FOUR;
  53. if( lPattern & (15L << 18L) )
  54. bBits |= CHORD_UPPER;
  55. bBits &= ~CHORD_COUNT;
  56. bBits |= count;
  57. return bBits;
  58. }
  59. // returns TRUE if the chord pattern represents a multichord, FALSE otherwise
  60. inline BOOL MultiChord(DWORD dwPattern)
  61. {
  62. BYTE bBits = setchordbits( dwPattern );
  63. short nChordCount = bBits & CHORD_COUNT;
  64. return !((bBits & CHORD_FOUR && nChordCount <= 4) ||
  65. (!(bBits & CHORD_FOUR) && nChordCount <= 3));
  66. }
  67. /*
  68. TListItem<DMExtendedChord*>* ConvertChord(
  69. DWORD dwChordPattern, BYTE bChordRoot, DWORD dwScalePattern, BYTE bScaleRoot)
  70. {
  71. BYTE bBits = setchordbits( dwChordPattern );
  72. short nChordCount = bBits & CHORD_COUNT;
  73. // The root of the lower chord is the input chord's root,
  74. // relative to the scale root.
  75. bChordRoot -= bScaleRoot;
  76. if (bChordRoot < 0) bChordRoot += 12;
  77. if ((bBits & CHORD_FOUR && nChordCount <= 4) ||
  78. (!(bBits & CHORD_FOUR) && nChordCount <= 3))
  79. {
  80. // single subchord with all info from input chord
  81. TListItem<DMExtendedChord*>* pSubChord = new TListItem<DMExtendedChord*>;
  82. if ( pSubChord == NULL ) return NULL;
  83. DMExtendedChord* pNew = new DMExtendedChord;
  84. if (!pNew)
  85. {
  86. delete pSubChord;
  87. return NULL;
  88. }
  89. DMExtendedChord*& rSubChord = pSubChord->GetItemValue();
  90. rSubChord = pNew;
  91. rSubChord->m_dwChordPattern = dwChordPattern;
  92. rSubChord->m_dwScalePattern = dwScalePattern;
  93. rSubChord->m_dwInvertPattern = 0xffffff; // default: inversions everywhere
  94. rSubChord->m_bRoot = bChordRoot;
  95. rSubChord->m_bScaleRoot = bScaleRoot;
  96. rSubChord->m_wCFlags = 0;
  97. // A single subchord can be used as either a bass or standard chord
  98. rSubChord->m_dwParts = (1 << SUBCHORD_BASS) | (1 << SUBCHORD_STANDARD_CHORD);
  99. rSubChord->AddRef();
  100. return pSubChord;
  101. }
  102. else
  103. {
  104. // two subchords both with scale and roots from input chord, and:
  105. // 1st chord: chord pattern from lower n notes of input chord
  106. // 2nd chord: chord pattern from upper n notes of input chord
  107. DWORD dwLowerSubChord = 0L;
  108. DWORD dwUpperSubChord = 0L;
  109. BYTE bUpperRoot = bChordRoot;
  110. DWORD dwPattern = dwChordPattern;
  111. short nIgnoreHigh = (bBits & CHORD_FOUR) ? 4 : 3;
  112. short nIgnoreLow = (bBits & CHORD_FOUR) ? nChordCount - 4 : nChordCount - 3;
  113. short nLowestUpper = 0;
  114. for (short nPos = 0, nCount = 0; nPos < 24; nPos++)
  115. {
  116. if (dwPattern & 1)
  117. {
  118. if (nCount < nIgnoreHigh)
  119. {
  120. dwLowerSubChord |= 1L << nPos;
  121. }
  122. if (nCount >= nIgnoreLow)
  123. {
  124. if (!nLowestUpper)
  125. {
  126. nLowestUpper = nPos;
  127. bUpperRoot = (bUpperRoot + (BYTE) nLowestUpper);
  128. }
  129. dwUpperSubChord |= 1L << (nPos - nLowestUpper);
  130. }
  131. nCount++;
  132. if (nCount >= nChordCount)
  133. break;
  134. }
  135. dwPattern >>= 1L;
  136. }
  137. // now, create the two subchords.
  138. TListItem<DMExtendedChord*>* pLowerSubChord = new TListItem<DMExtendedChord*>;
  139. if ( pLowerSubChord == NULL ) return NULL;
  140. DMExtendedChord* pLower = new DMExtendedChord;
  141. if (!pLower)
  142. {
  143. delete pLowerSubChord;
  144. return NULL;
  145. }
  146. DMExtendedChord*& rLowerSubChord = pLowerSubChord->GetItemValue();
  147. rLowerSubChord = pLower;
  148. rLowerSubChord->m_dwChordPattern = dwLowerSubChord;
  149. rLowerSubChord->m_dwScalePattern = dwScalePattern;
  150. rLowerSubChord->m_dwInvertPattern = 0xffffff; // default: inversions everywhere
  151. rLowerSubChord->m_bRoot = bChordRoot;
  152. rLowerSubChord->m_bScaleRoot = bScaleRoot;
  153. rLowerSubChord->m_wCFlags = 0;
  154. rLowerSubChord->m_dwParts = (1 << SUBCHORD_BASS); // the lower chord is the bass chord
  155. TListItem<DMExtendedChord*>* pUpperSubChord = new TListItem<DMExtendedChord*>;
  156. if ( pUpperSubChord == NULL ) return NULL;
  157. DMExtendedChord* pUpper = new DMExtendedChord;
  158. if (!pUpper)
  159. {
  160. delete pUpperSubChord;
  161. return NULL;
  162. }
  163. DMExtendedChord*& rUpperSubChord = pUpperSubChord->GetItemValue();
  164. rUpperSubChord = pUpper;
  165. rUpperSubChord->m_dwChordPattern = dwUpperSubChord;
  166. rUpperSubChord->m_dwScalePattern = dwScalePattern;
  167. rUpperSubChord->m_dwInvertPattern = 0xffffff; // default: inversions everywhere
  168. rUpperSubChord->m_bRoot = bUpperRoot % 24;
  169. while (rUpperSubChord->m_bRoot < rLowerSubChord->m_bRoot)
  170. rUpperSubChord->m_bRoot += 12;
  171. rUpperSubChord->m_bScaleRoot = bScaleRoot;
  172. rUpperSubChord->m_wCFlags = 0;
  173. rUpperSubChord->m_dwParts = (1 << SUBCHORD_STANDARD_CHORD); // the upper chord is the standard chord
  174. rLowerSubChord->AddRef();
  175. rUpperSubChord->AddRef();
  176. return pLowerSubChord->Cat(pUpperSubChord);
  177. }
  178. }
  179. */
  180. /////////////////////////////////////////////////////////////////////////////
  181. // CDMPers
  182. CDMPers::CDMPers( ) : m_cRef(1), m_fCSInitialized(FALSE)
  183. {
  184. InterlockedIncrement(&g_cComponent);
  185. // Do this first since it might throw an exception
  186. //
  187. ::InitializeCriticalSection( &m_CriticalSection );
  188. m_fCSInitialized = TRUE;
  189. m_PersonalityInfo.m_fLoaded = false;
  190. ZeroMemory(&m_PersonalityInfo.m_guid, sizeof(GUID));
  191. }
  192. CDMPers::~CDMPers()
  193. {
  194. if (m_fCSInitialized)
  195. {
  196. CleanUp();
  197. ::DeleteCriticalSection( &m_CriticalSection );
  198. }
  199. InterlockedDecrement(&g_cComponent);
  200. }
  201. void CDMPers::CleanUp()
  202. {
  203. m_PersonalityInfo.m_fLoaded = false;
  204. ZeroMemory(&m_PersonalityInfo.m_guid, sizeof(GUID));
  205. TListItem<DMChordEntry>* pEntry = m_PersonalityInfo.m_ChordMap.GetHead();
  206. for(; pEntry; pEntry=pEntry->GetNext())
  207. {
  208. pEntry->GetItemValue().m_ChordData.Release();
  209. }
  210. m_PersonalityInfo.m_ChordMap.CleanUp();
  211. for (short i = 0; i < 24; i++)
  212. {
  213. TListItem<DMChordData>* pData = m_PersonalityInfo.m_aChordPalette[i].GetHead();
  214. for(; pData; pData=pData->GetNext())
  215. {
  216. pData->GetItemValue().Release();
  217. }
  218. m_PersonalityInfo.m_aChordPalette[i].CleanUp();
  219. }
  220. TListItem<DMSignPost>* pSignPost = m_PersonalityInfo.m_SignPostList.GetHead();
  221. for (; pSignPost != NULL; pSignPost = pSignPost->GetNext())
  222. {
  223. DMSignPost& rSignPost = pSignPost->GetItemValue();
  224. rSignPost.m_ChordData.Release();
  225. rSignPost.m_aCadence[0].Release();
  226. rSignPost.m_aCadence[1].Release();
  227. }
  228. m_PersonalityInfo.m_SignPostList.CleanUp();
  229. }
  230. STDMETHODIMP CDMPers::QueryInterface(
  231. const IID &iid,
  232. void **ppv)
  233. {
  234. V_INAME(CDMPers::QueryInterface);
  235. V_PTRPTR_WRITE(ppv);
  236. V_REFGUID(iid);
  237. *ppv = NULL;
  238. if (iid == IID_IUnknown || iid == IID_IDirectMusicChordMap)
  239. {
  240. *ppv = static_cast<IDirectMusicChordMap*>(this);
  241. }
  242. else if (iid == IID_IPersistStream)
  243. {
  244. *ppv = static_cast<IPersistStream*>(this);
  245. }
  246. else if (iid == IID_IDirectMusicObject)
  247. {
  248. *ppv = static_cast<IDirectMusicObject*>(this);
  249. }
  250. else if (iid == IID_IDMPers)
  251. {
  252. *ppv = static_cast<IDMPers*>(this);
  253. }
  254. if (*ppv == NULL)
  255. return E_NOINTERFACE;
  256. reinterpret_cast<IUnknown*>(this)->AddRef();
  257. return S_OK;
  258. }
  259. STDMETHODIMP_(ULONG) CDMPers::AddRef()
  260. {
  261. return InterlockedIncrement(&m_cRef);
  262. }
  263. STDMETHODIMP_(ULONG) CDMPers::Release()
  264. {
  265. if (!InterlockedDecrement(&m_cRef))
  266. {
  267. m_cRef = 100; // artificial reference count to prevent reentrency due to COM aggregation
  268. delete this;
  269. return 0;
  270. }
  271. return m_cRef;
  272. }
  273. HRESULT CDMPers::GetPersonalityStruct(void** ppPersonality)
  274. {
  275. if (ppPersonality)
  276. *ppPersonality = &m_PersonalityInfo;
  277. return S_OK;
  278. }
  279. HRESULT CDMPers::GetDescriptor(LPDMUS_OBJECTDESC pDesc)
  280. {
  281. // Argument validation
  282. V_INAME(CDMPers::GetDescriptor);
  283. V_PTR_WRITE(pDesc, DMUS_OBJECTDESC);
  284. EnterCriticalSection( &m_CriticalSection );
  285. ZeroMemory(pDesc, sizeof(DMUS_OBJECTDESC));
  286. pDesc->dwSize = sizeof(DMUS_OBJECTDESC);
  287. pDesc->dwValidData = DMUS_OBJ_CLASS;
  288. pDesc->guidClass = CLSID_DirectMusicChordMap;
  289. if (m_PersonalityInfo.m_fLoaded)
  290. {
  291. pDesc->dwValidData |= DMUS_OBJ_LOADED;
  292. }
  293. if (m_PersonalityInfo.m_guid.Data1 || m_PersonalityInfo.m_guid.Data2)
  294. {
  295. pDesc->dwValidData |= DMUS_OBJ_OBJECT;
  296. pDesc->guidObject = m_PersonalityInfo.m_guid;
  297. }
  298. if (m_PersonalityInfo.m_strName)
  299. {
  300. pDesc->dwValidData |= DMUS_OBJ_NAME;
  301. wcscpy(pDesc->wszName, m_PersonalityInfo.m_strName);
  302. //MultiByteToWideChar( CP_ACP, 0, m_PersonalityInfo.m_strName, -1, pDesc->wszName, DMUS_MAX_NAME);
  303. }
  304. LeaveCriticalSection( &m_CriticalSection );
  305. return S_OK;
  306. }
  307. HRESULT CDMPers::SetDescriptor(LPDMUS_OBJECTDESC pDesc)
  308. {
  309. // Argument validation
  310. V_INAME(CDMPers::SetDescriptor);
  311. V_PTR_WRITE(pDesc, DMUS_OBJECTDESC);
  312. HRESULT hr = E_INVALIDARG;
  313. DWORD dw = 0;
  314. EnterCriticalSection( &m_CriticalSection );
  315. if( pDesc->dwSize >= sizeof(DMUS_OBJECTDESC) )
  316. {
  317. if( pDesc->dwValidData & DMUS_OBJ_OBJECT )
  318. {
  319. m_PersonalityInfo.m_guid = pDesc->guidObject;
  320. dw |= DMUS_OBJ_OBJECT;
  321. }
  322. if( pDesc->dwValidData & DMUS_OBJ_NAME )
  323. {
  324. m_PersonalityInfo.m_strName = pDesc->wszName;
  325. dw |= DMUS_OBJ_NAME;
  326. }
  327. if( pDesc->dwValidData & (~dw) )
  328. {
  329. Trace(2, "WARNING: SetDescriptor (chord map): Descriptor contains fields that were not set.\n");
  330. hr = S_FALSE; // there were extra fields we didn't parse;
  331. pDesc->dwValidData = dw;
  332. }
  333. else
  334. {
  335. hr = S_OK;
  336. }
  337. }
  338. LeaveCriticalSection( &m_CriticalSection );
  339. return hr;
  340. }
  341. HRESULT CDMPers::ParseDescriptor(LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc)
  342. {
  343. // Argument validation
  344. V_INAME(CDMPers::ParseDescriptor);
  345. V_INTERFACE(pStream);
  346. V_PTR_WRITE(pDesc, DMUS_OBJECTDESC);
  347. IAARIFFStream* pIRiffStream;
  348. MMCKINFO ckMain;
  349. // Prsonality personality;
  350. // DWORD dwSize;
  351. // FOURCC id;
  352. DWORD dwPos;
  353. HRESULT hr = S_OK;
  354. dwPos = StreamTell( pStream );
  355. BOOL fFoundFormat = FALSE;
  356. // Check for Direct Music format
  357. hr = AllocRIFFStream( pStream, &pIRiffStream );
  358. if( SUCCEEDED( hr ) )
  359. {
  360. ckMain.fccType = DMUS_FOURCC_CHORDMAP_FORM;
  361. if( pIRiffStream->Descend( &ckMain, NULL, MMIO_FINDRIFF ) == 0 )
  362. {
  363. hr = DM_ParseDescriptor( pIRiffStream, &ckMain, pDesc );
  364. fFoundFormat = TRUE;
  365. }
  366. pIRiffStream->Release();
  367. }
  368. else
  369. {
  370. return hr;
  371. }
  372. if( !fFoundFormat )
  373. {
  374. /* Don't try to parse IMA 2.5 format
  375. StreamSeek( pStream, dwPos, STREAM_SEEK_SET );
  376. if( FAILED( pStream->Read( &id, sizeof( FOURCC ), NULL ) ) ||
  377. !GetMLong( pStream, dwSize ) )
  378. {
  379. */
  380. Trace(1, "ERROR: ParseDescriptor (chord map): File does not contain a valid chord map.\n");
  381. return DMUS_E_CHUNKNOTFOUND;
  382. /*
  383. }
  384. if( id != mmioFOURCC( 'R', 'E', 'P', 's' ) )
  385. {
  386. Trace(1, "ERROR: ParseDescriptor (chord map): File does not contain a valid chord map.\n");
  387. return DMUS_E_CHUNKNOTFOUND;
  388. }
  389. pDesc->dwValidData = DMUS_OBJ_CLASS;
  390. pDesc->guidClass = CLSID_DirectMusicChordMap;
  391. GetMLong( pStream, dwSize );
  392. if( SUCCEEDED( pStream->Read( &personality, min( sizeof(Prsonality), dwSize ), NULL ) ) )
  393. {
  394. MultiByteToWideChar( CP_ACP, 0, personality.name, -1, pDesc->wszName, DMUS_MAX_NAME);
  395. if (pDesc->wszName[0])
  396. {
  397. pDesc->dwValidData |= DMUS_OBJ_NAME;
  398. }
  399. }
  400. */
  401. }
  402. return S_OK;
  403. }
  404. /////////////////////////////////////////////////////////////////////////////
  405. // IDirectMusicPersonality
  406. /*
  407. @method:(EXTERNAL) HRESULT | IDirectMusicPersonality | GetScale | Retrieves the scale
  408. associated with the personality.
  409. @rdesc Returns:
  410. @flag S_OK | Success.
  411. @flag E_POINTER | <p pdwScale> is not a valid pointer.
  412. @comm The scale is defined by the bits in a DWORD, split into a scale pattern (lower 24 bits)
  413. and a root (upper 8 bits) For the scale pattern, the low bit (0x0001) is the lowest note in the
  414. scale, the next higher (0x0002) is a semitone higher, etc. for two octaves. The root is
  415. represented as a number between 0 and 23, where 0 represents a low C, 1 represents the
  416. C# above that, etc. for two octaves.
  417. */
  418. HRESULT CDMPers::GetScale(
  419. DWORD *pdwScale // @parm The scale value to be returned.
  420. )
  421. {
  422. V_PTR_WRITE(pdwScale, sizeof(DWORD) );
  423. *pdwScale = m_PersonalityInfo.m_dwScalePattern;
  424. return S_OK;
  425. }
  426. /////////////////////////////////////////////////////////////////////////////
  427. // IPersist
  428. HRESULT CDMPers::GetClassID( LPCLSID pclsid )
  429. {
  430. if ( pclsid == NULL ) return E_INVALIDARG;
  431. *pclsid = CLSID_DirectMusicChordMap;
  432. return S_OK;
  433. }
  434. /////////////////////////////////////////////////////////////////////////////
  435. // IPersistStream
  436. HRESULT CDMPers::IsDirty()
  437. {
  438. return ( m_fDirty ) ? S_OK : S_FALSE;
  439. }
  440. HRESULT CDMPers::Save( LPSTREAM /*pStream*/, BOOL /*fClearDirty*/ )
  441. {
  442. return E_NOTIMPL;
  443. }
  444. HRESULT CDMPers::GetSizeMax( ULARGE_INTEGER FAR* /*pcbSize*/ )
  445. {
  446. return E_NOTIMPL;
  447. }
  448. HRESULT CDMPers::Load( LPSTREAM pStream )
  449. {
  450. //FOURCC id;
  451. //DWORD dwSize;
  452. DWORD dwPos;
  453. IAARIFFStream* pIRiffStream;
  454. MMCKINFO ckMain;
  455. HRESULT hr = E_FAIL;
  456. if ( pStream == NULL ) return E_INVALIDARG;
  457. EnterCriticalSection( &m_CriticalSection );
  458. CleanUp();
  459. dwPos = StreamTell( pStream );
  460. BOOL fFoundFormat = FALSE;
  461. // Check for Direct Music format
  462. if( SUCCEEDED( AllocRIFFStream( pStream, &pIRiffStream ) ) )
  463. {
  464. ckMain.fccType = DMUS_FOURCC_CHORDMAP_FORM;
  465. if( pIRiffStream->Descend( &ckMain, NULL, MMIO_FINDRIFF ) == 0 )
  466. {
  467. hr = DM_LoadPersonality( pIRiffStream, &ckMain );
  468. fFoundFormat = TRUE;
  469. }
  470. pIRiffStream->Release();
  471. }
  472. if( !fFoundFormat )
  473. {
  474. /* Don't try to load IMA 2.5 format
  475. StreamSeek( pStream, dwPos, STREAM_SEEK_SET );
  476. if( FAILED( pStream->Read( &id, sizeof( FOURCC ), NULL ) ) ||
  477. !GetMLong( pStream, dwSize ) )
  478. {
  479. */
  480. Trace(1, "ERROR: Load (chord map): File does not contain a valid chord map.\n");
  481. hr = DMUS_E_CHUNKNOTFOUND;
  482. goto end;
  483. /*
  484. }
  485. if( id != mmioFOURCC( 'R', 'E', 'P', 's' ) )
  486. {
  487. Trace(1, "ERROR: Load (chord map): File does not contain a valid chord map.\n");
  488. hr = DMUS_E_CHUNKNOTFOUND;
  489. goto end;
  490. }
  491. hr = LoadPersonality( pStream, dwSize );
  492. */
  493. }
  494. end:
  495. if (SUCCEEDED(hr)) m_PersonalityInfo.m_fLoaded = true;
  496. LeaveCriticalSection( &m_CriticalSection );
  497. return hr;
  498. }
  499. /*
  500. static LPSINEPOST loadasignpost( LPSTREAM pStream, DWORD dwSize )
  501. {
  502. LPSINEPOST signpost;
  503. signpost = new SinePost;
  504. if( signpost == NULL )
  505. {
  506. StreamSeek( pStream, dwSize, STREAM_SEEK_CUR );
  507. return NULL;
  508. }
  509. if( dwSize > sizeof(SinePost) )
  510. {
  511. pStream->Read( signpost, sizeof(SinePost), NULL );
  512. FixBytes( FBT_SINEPOST, signpost );
  513. StreamSeek( pStream, dwSize - sizeof(SinePost), STREAM_SEEK_CUR );
  514. }
  515. else
  516. {
  517. pStream->Read( signpost, dwSize, NULL );
  518. FixBytes( FBT_SINEPOST, signpost );
  519. }
  520. signpost->pNext = 0;
  521. signpost->chord.pNext = 0;
  522. signpost->cadence[0].pNext = 0;
  523. signpost->cadence[1].pNext = 0;
  524. return signpost;
  525. }
  526. static LPNEXTCHRD loadnextchords( LPSTREAM pStream, DWORD dwSiz )
  527. {
  528. HRESULT hr = S_OK;
  529. LPNEXTCHRD nextchordlist = NULL;
  530. LPNEXTCHRD nextchord;
  531. DWORD nodesize = 0;
  532. long lSize = dwSiz;
  533. if (!GetMLong( pStream, nodesize ))
  534. {
  535. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  536. return NULL;
  537. }
  538. lSize -= 4;
  539. while( lSize > 0 )
  540. {
  541. nextchord = new NextChrd;
  542. if( nextchord == NULL )
  543. {
  544. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  545. break;
  546. }
  547. if( nodesize > NEXTCHORD_SIZE )
  548. {
  549. hr = pStream->Read( &nextchord->dwflags, NEXTCHORD_SIZE, NULL );
  550. FixBytes( FBT_NEXTCHRD, nextchord );
  551. StreamSeek( pStream, nodesize - NEXTCHORD_SIZE, STREAM_SEEK_CUR );
  552. }
  553. else
  554. {
  555. pStream->Read( &nextchord->dwflags, nodesize, NULL );
  556. FixBytes( FBT_NEXTCHRD, nextchord );
  557. }
  558. lSize -= nodesize;
  559. if (SUCCEEDED(hr))
  560. {
  561. nextchord->pNext = 0;
  562. nextchordlist = List_Cat( nextchordlist, nextchord );
  563. }
  564. else
  565. {
  566. delete nextchord;
  567. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  568. break;
  569. }
  570. }
  571. return nextchordlist;
  572. }
  573. static LPCHRDENTRY loadachordentry( LPSTREAM pStream, DWORD dwSiz )
  574. {
  575. LPCHRDENTRY chordentry;
  576. DWORD csize = 0;
  577. DWORD segsize = 0;
  578. DWORD id;
  579. long lSize = dwSiz;
  580. chordentry = new ChrdEntry;
  581. if( chordentry == NULL )
  582. {
  583. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  584. return NULL;
  585. }
  586. if (!GetMLong( pStream, csize ))
  587. {
  588. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  589. delete chordentry;
  590. return NULL;
  591. }
  592. lSize -= 4;
  593. if( csize > CHORDENTRY_SIZE )
  594. {
  595. pStream->Read( &chordentry->chord.time, CHORDENTRY_SIZE, NULL );
  596. FixBytes( FBT_CHRDENTRY, chordentry );
  597. StreamSeek( pStream, csize - CHORDENTRY_SIZE, STREAM_SEEK_CUR );
  598. }
  599. else
  600. {
  601. pStream->Read( &chordentry->chord.time, csize, NULL );
  602. FixBytes( FBT_CHRDENTRY, chordentry );
  603. }
  604. lSize -= csize;
  605. chordentry->pNext = 0;
  606. chordentry->nextchordlist = 0;
  607. chordentry->chord.pNext = 0;
  608. while( lSize > 0 )
  609. {
  610. pStream->Read( &id, sizeof(id), NULL );
  611. if (!GetMLong( pStream, segsize ))
  612. {
  613. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  614. break;
  615. }
  616. lSize -= 8;
  617. switch( id )
  618. {
  619. case mmioFOURCC( 'L', 'X', 'N', 's' ):
  620. chordentry->nextchordlist = loadnextchords( pStream, segsize );
  621. break;
  622. default:
  623. StreamSeek( pStream, segsize, STREAM_SEEK_CUR );
  624. break;
  625. }
  626. lSize -= segsize;
  627. }
  628. return chordentry;
  629. }
  630. void DMPersonalityStruct::ResolveConnections( LPPERSONALITY personality, short nCount )
  631. {
  632. LPCHRDENTRY entry;
  633. LPNEXTCHRD nextchord;
  634. if (nCount == 0)
  635. {
  636. return;
  637. }
  638. // nCount is the largest index, so the array needs to be one more than that
  639. TListItem<DMChordEntry> **ChordMap = new TListItem<DMChordEntry> *[nCount + 1];
  640. if (!ChordMap) return;
  641. for( entry=personality->chordlist ; entry ; entry=entry->pNext )
  642. {
  643. TListItem<DMChordEntry>* pEntry = new TListItem<DMChordEntry>;
  644. if (!pEntry)
  645. {
  646. delete [] ChordMap;
  647. return;
  648. }
  649. DMChordEntry& rEntry = pEntry->GetItemValue();
  650. rEntry.m_dwFlags = entry->dwflags;
  651. rEntry.m_ChordData.m_strName = entry->chord.name;
  652. rEntry.m_ChordData.m_pSubChords = ConvertChord(
  653. entry->chord.pattern, entry->chord.root, entry->chord.scalepattern, 0);
  654. m_ChordMap.AddHead(pEntry);
  655. ChordMap[entry->nid] = pEntry;
  656. nextchord = entry->nextchordlist;
  657. for( ; nextchord ; nextchord=nextchord->pNext )
  658. {
  659. if( nextchord->nid )
  660. {
  661. TListItem<DMChordLink>* pLink = new TListItem<DMChordLink>;
  662. if (!pLink)
  663. {
  664. delete [] ChordMap;
  665. return;
  666. }
  667. DMChordLink& rLink = pLink->GetItemValue();
  668. rLink.m_wWeight = nextchord->nweight;
  669. rLink.m_wMinBeats = nextchord->nminbeats;
  670. rLink.m_wMaxBeats = nextchord->nmaxbeats;
  671. rLink.m_dwFlags = nextchord->dwflags;
  672. rLink.m_nID = nextchord->nid;
  673. rEntry.m_Links.AddHead(pLink);
  674. }
  675. }
  676. }
  677. for(TListItem<DMChordEntry>* pEntry=m_ChordMap.GetHead(); pEntry; pEntry=pEntry->GetNext())
  678. {
  679. TListItem<DMChordLink>* pLink = pEntry->GetItemValue().m_Links.GetHead();
  680. for( ; pLink ; pLink = pLink->GetNext() )
  681. {
  682. DMChordLink& rLink = pLink->GetItemValue();
  683. if( rLink.m_nID )
  684. {
  685. rLink.m_pChord = ChordMap[rLink.m_nID];
  686. }
  687. }
  688. }
  689. delete [] ChordMap;
  690. }
  691. HRESULT CDMPers::LoadPersonality( LPSTREAM pStream, DWORD dwSiz )
  692. {
  693. short i;
  694. LPPERSONALITY personality;
  695. LPCHRDENTRY chordentry;
  696. LPSINEPOST signpost;
  697. DWORD csize = 0;
  698. DWORD segsize = 0;
  699. FOURCC id;
  700. short nCount = 0;
  701. long lSize = dwSiz;
  702. HRESULT hr = S_OK;
  703. if ( pStream == NULL ) return E_INVALIDARG;
  704. personality = new Prsonality;
  705. if( personality == NULL )
  706. {
  707. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  708. return E_OUTOFMEMORY;
  709. }
  710. if (!GetMLong( pStream, csize ))
  711. {
  712. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  713. delete personality;
  714. return E_FAIL;
  715. }
  716. lSize -= 4;
  717. if( csize > sizeof(Prsonality) )
  718. {
  719. pStream->Read( personality, sizeof(Prsonality), NULL );
  720. FixBytes( FBT_PRSONALITY, personality );
  721. StreamSeek( pStream, csize - sizeof(Prsonality), STREAM_SEEK_CUR );
  722. }
  723. else
  724. {
  725. pStream->Read( personality, csize, NULL );
  726. FixBytes( FBT_PRSONALITY, personality );
  727. }
  728. lSize -= csize;
  729. m_PersonalityInfo.m_strName = personality->name;
  730. m_PersonalityInfo.m_dwScalePattern = personality->scalepattern;
  731. personality->pNext = NULL;
  732. personality->dwAA = 0;
  733. personality->chordlist = NULL;
  734. personality->signpostlist = NULL;
  735. personality->playlist = 0;
  736. personality->firstchord = NULL;
  737. for( i=0 ; i<24 ; i++ )
  738. {
  739. TListItem<DMChordData>* pPaletteEntry = new TListItem<DMChordData>;
  740. if (!pPaletteEntry)
  741. {
  742. hr = E_OUTOFMEMORY;
  743. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  744. break;
  745. }
  746. DMChordData& rChordData = pPaletteEntry->GetItemValue();
  747. rChordData.m_strName = personality->chord[i].achName;
  748. rChordData.m_pSubChords = ConvertChord(
  749. personality->chord[i].lPattern, personality->chord[i].chRoot,
  750. personality->chord[i].lScalePattern, 0);
  751. m_PersonalityInfo.m_aChordPalette[i].AddTail(pPaletteEntry);
  752. personality->chord[i].pNext = 0;
  753. }
  754. if (SUCCEEDED(hr))
  755. {
  756. while( lSize > 0 )
  757. {
  758. pStream->Read( &id, sizeof(id), NULL );
  759. if (!GetMLong( pStream, segsize ))
  760. {
  761. StreamSeek( pStream, lSize, STREAM_SEEK_CUR );
  762. break;
  763. }
  764. lSize -= 8;
  765. switch( id )
  766. {
  767. case mmioFOURCC( 'N', 'E', 'C', 's' ):
  768. chordentry = loadachordentry( pStream, segsize );
  769. if( chordentry )
  770. {
  771. personality->chordlist = List_Cat( personality->chordlist, chordentry );
  772. if (chordentry->nid > nCount)
  773. nCount = chordentry->nid;
  774. }
  775. break;
  776. case mmioFOURCC( 'P', 'N', 'S', 's' ):
  777. signpost = loadasignpost( pStream, segsize );
  778. if( signpost )
  779. {
  780. personality->signpostlist = List_Cat( personality->signpostlist, signpost );
  781. TListItem<DMSignPost>* pSignPost = new TListItem<DMSignPost>;
  782. if (!pSignPost)
  783. {
  784. hr = E_OUTOFMEMORY;
  785. StreamSeek( pStream, segsize, STREAM_SEEK_CUR );
  786. break;
  787. }
  788. DMSignPost& rSignPost = pSignPost->GetItemValue();
  789. rSignPost.m_dwChords = signpost->chords;
  790. rSignPost.m_dwFlags = signpost->flags;
  791. rSignPost.m_dwTempFlags = signpost->tempflags;
  792. rSignPost.m_ChordData.m_strName = signpost->chord.name;
  793. rSignPost.m_ChordData.m_pSubChords = ConvertChord(
  794. signpost->chord.pattern, signpost->chord.root,
  795. signpost->chord.scalepattern, 0);
  796. rSignPost.m_aCadence[0].m_strName = signpost->cadence[0].name;
  797. rSignPost.m_aCadence[0].m_pSubChords = ConvertChord(
  798. signpost->cadence[0].pattern, signpost->cadence[0].root,
  799. signpost->cadence[0].scalepattern, 0);
  800. rSignPost.m_aCadence[1].m_strName = signpost->cadence[1].name;
  801. rSignPost.m_aCadence[1].m_pSubChords = ConvertChord(
  802. signpost->cadence[1].pattern, signpost->cadence[1].root,
  803. signpost->cadence[1].scalepattern, 0);
  804. m_PersonalityInfo.m_SignPostList.AddTail(pSignPost);
  805. }
  806. break;
  807. default:
  808. StreamSeek( pStream, segsize, STREAM_SEEK_CUR );
  809. break;
  810. }
  811. lSize -= segsize;
  812. }
  813. }
  814. if (SUCCEEDED(hr))
  815. {
  816. m_PersonalityInfo.ResolveConnections( personality, nCount );
  817. }
  818. // free up all the old format data structures
  819. LPCHRDENTRY pChord;
  820. LPNEXTCHRD pNextChord;
  821. LPNEXTCHRD pNextNextChord;
  822. for( pChord = personality->chordlist ; pChord != NULL ; pChord = pChord->pNext )
  823. {
  824. for( pNextChord = pChord->nextchordlist ; pNextChord != NULL ; pNextChord = pNextNextChord )
  825. {
  826. pNextNextChord = pNextChord->pNext;
  827. delete pNextChord;
  828. }
  829. }
  830. List_Free( personality->chordlist );
  831. List_Free( personality->signpostlist );
  832. delete personality;
  833. return hr;
  834. }
  835. */
  836. HRESULT CDMPers::DM_ParseDescriptor( IAARIFFStream* pIRiffStream, MMCKINFO* pckMain, LPDMUS_OBJECTDESC pDesc )
  837. {
  838. IStream* pIStream;
  839. MMCKINFO ck;
  840. DWORD dwByteCount;
  841. DWORD dwSize;
  842. DWORD dwPos;
  843. HRESULT hr = S_OK;
  844. short nCount = 0;
  845. pIStream = pIRiffStream->GetStream();
  846. if ( pIStream == NULL ) return E_FAIL;
  847. dwPos = StreamTell( pIStream );
  848. pDesc->dwValidData = DMUS_OBJ_CLASS;
  849. pDesc->guidClass = CLSID_DirectMusicChordMap;
  850. while( pIRiffStream->Descend( &ck, pckMain, 0 ) == 0 )
  851. {
  852. switch( ck.ckid )
  853. {
  854. case DMUS_FOURCC_IOCHORDMAP_CHUNK:
  855. {
  856. DMUS_IO_CHORDMAP iPersonality;
  857. dwSize = min( ck.cksize, sizeof( DMUS_IO_CHORDMAP ) );
  858. hr = pIStream->Read( &iPersonality, dwSize, &dwByteCount );
  859. if( FAILED( hr ) || dwByteCount != dwSize )
  860. {
  861. Trace(1, "ERROR: ParseDescriptor (chord map): DMUS_FOURCC_IOCHORDMAP_CHUNK chunk does not contain a valid DMUS_IO_CHORDMAP.\n");
  862. hr = DMUS_E_CHUNKNOTFOUND;
  863. goto ON_END;
  864. }
  865. wcscpy(pDesc->wszName, iPersonality.wszLoadName);
  866. if(pDesc->wszName[0])
  867. {
  868. pDesc->dwValidData |= DMUS_OBJ_NAME;
  869. pDesc->wszName[16] = 0;
  870. }
  871. break;
  872. }
  873. case DMUS_FOURCC_GUID_CHUNK:
  874. dwSize = min( ck.cksize, sizeof( GUID ) );
  875. hr = pIStream->Read( &pDesc->guidObject, dwSize, &dwByteCount );
  876. if( FAILED( hr ) || dwByteCount != dwSize )
  877. {
  878. Trace(1, "ERROR: ParseDescriptor (chord map): DMUS_FOURCC_GUID_CHUNK chunk does not contain a valid GUID.\n");
  879. hr = DMUS_E_CHUNKNOTFOUND;
  880. goto ON_END;
  881. }
  882. pDesc->dwValidData |= DMUS_OBJ_OBJECT;
  883. break;
  884. }
  885. pIRiffStream->Ascend( &ck, 0 );
  886. dwPos = StreamTell( pIStream );
  887. }
  888. ON_END:
  889. pIStream->Release();
  890. return hr;
  891. }
  892. HRESULT CDMPers::DM_LoadPersonality( IAARIFFStream* pIRiffStream, MMCKINFO* pckMain )
  893. {
  894. IStream* pIStream;
  895. MMCKINFO ck;
  896. MMCKINFO ck1;
  897. MMCKINFO ckList;
  898. DWORD dwByteCount;
  899. DWORD dwSize;
  900. DWORD dwPos;
  901. HRESULT hr = S_OK;
  902. DMExtendedChord** apChordDB = NULL;
  903. short nCount = 0;
  904. short n;
  905. pIStream = pIRiffStream->GetStream();
  906. if ( pIStream == NULL ) return E_FAIL;
  907. dwPos = StreamTell( pIStream );
  908. while( pIRiffStream->Descend( &ck, pckMain, 0 ) == 0 )
  909. {
  910. switch( ck.ckid )
  911. {
  912. case DMUS_FOURCC_IOCHORDMAP_CHUNK:
  913. {
  914. DMUS_IO_CHORDMAP iPersonality;
  915. ZeroMemory(&iPersonality, sizeof(DMUS_IO_CHORDMAP));
  916. iPersonality.dwScalePattern = 0xffffffff;
  917. dwSize = min( ck.cksize, sizeof( DMUS_IO_CHORDMAP ) );
  918. hr = pIStream->Read( &iPersonality, dwSize, &dwByteCount );
  919. if( FAILED( hr ) || dwByteCount != dwSize )
  920. {
  921. Trace(1, "ERROR: Load (chord map): DMUS_FOURCC_IOCHORDMAP_CHUNK chunk does not contain a valid DMUS_IO_CHORDMAP.\n");
  922. if (SUCCEEDED(hr)) hr = DMUS_E_CANNOTREAD;
  923. goto ON_END;
  924. }
  925. if( iPersonality.dwFlags & 0xffff0000 )
  926. {
  927. // the scale was not properly initialized
  928. Trace(2, "WARNING: Load (chord map): The chord map's flags are not properly initialized; clearing flags.\n");
  929. iPersonality.dwFlags = 0;
  930. }
  931. if( !(iPersonality.dwFlags & DMUS_CHORDMAPF_VERSION8) &&
  932. iPersonality.dwScalePattern >> 24 )
  933. {
  934. // the scale was not properly initialized
  935. Trace(1, "ERROR: Load (chord map): The chord map's scale is not properly initialized.\n");
  936. hr = DMUS_E_NOT_INIT;
  937. goto ON_END;
  938. }
  939. m_PersonalityInfo.m_strName = iPersonality.wszLoadName;
  940. m_PersonalityInfo.m_dwScalePattern = iPersonality.dwScalePattern;
  941. m_PersonalityInfo.m_dwChordMapFlags = iPersonality.dwFlags;
  942. break;
  943. }
  944. case DMUS_FOURCC_GUID_CHUNK:
  945. dwSize = min( ck.cksize, sizeof( GUID ) );
  946. hr = pIStream->Read( &m_PersonalityInfo.m_guid, dwSize, &dwByteCount );
  947. if( FAILED( hr ) || dwByteCount != dwSize )
  948. {
  949. Trace(1, "ERROR: Load (chord map): DMUS_FOURCC_GUID_CHUNK chunk does not contain a valid GUID.\n");
  950. if (SUCCEEDED(hr)) hr = DMUS_E_CANNOTREAD;
  951. goto ON_END;
  952. }
  953. break;
  954. case DMUS_FOURCC_SUBCHORD_CHUNK:
  955. {
  956. long lFileSize = ck.cksize;
  957. WORD wSize;
  958. DWORD cb;
  959. hr = pIStream->Read( &wSize, sizeof( wSize ), &cb );
  960. if (FAILED(hr) || cb != sizeof( wSize ) )
  961. {
  962. Trace(1, "ERROR: Load (chord map): DMUS_FOURCC_SUBCHORD_CHUNK chunk does not contain a valid size DWORD.\n");
  963. if (SUCCEEDED(hr)) hr = DMUS_E_CANNOTREAD;
  964. pIRiffStream->Ascend( &ck, 0 );
  965. goto ON_END;
  966. }
  967. lFileSize -= cb;
  968. TList<DMExtendedChord*> ChordList;
  969. while (lFileSize > 0)
  970. {
  971. DMUS_IO_PERS_SUBCHORD iSubChord;
  972. hr = pIStream->Read( &iSubChord, wSize, &cb );
  973. if (FAILED(hr) || cb != wSize )
  974. {
  975. Trace(1, "ERROR: Load (chord map): DMUS_FOURCC_SUBCHORD_CHUNK chunk does not contain a valid DMUS_IO_PERS_SUBCHORD.\n");
  976. if (SUCCEEDED(hr)) hr = DMUS_E_CANNOTREAD;
  977. pIRiffStream->Ascend( &ck, 0 );
  978. goto ON_END;
  979. }
  980. // stuff the data into a subchord struct and add it to the chord list
  981. // (in reverse order)
  982. TListItem<DMExtendedChord*>* pChordItem = new TListItem<DMExtendedChord*>;
  983. if (pChordItem)
  984. {
  985. DMExtendedChord*& rpChord = pChordItem->GetItemValue();
  986. rpChord = new DMExtendedChord;
  987. if (rpChord)
  988. {
  989. rpChord->m_dwChordPattern = iSubChord.dwChordPattern;
  990. rpChord->m_dwScalePattern = iSubChord.dwScalePattern;
  991. rpChord->m_dwInvertPattern = iSubChord.dwInvertPattern;
  992. rpChord->m_bRoot = iSubChord.bChordRoot;
  993. rpChord->m_bScaleRoot = iSubChord.bScaleRoot;
  994. rpChord->m_wCFlags = iSubChord.wCFlags;
  995. rpChord->m_dwParts = iSubChord.dwLevels;
  996. nCount++;
  997. ChordList.AddHead(pChordItem);
  998. }
  999. else
  1000. {
  1001. delete pChordItem;
  1002. pChordItem = NULL;
  1003. }
  1004. }
  1005. if (!pChordItem)
  1006. {
  1007. hr = E_OUTOFMEMORY;
  1008. goto ON_END;
  1009. }
  1010. lFileSize -= wSize;
  1011. }
  1012. if (lFileSize != 0 )
  1013. {
  1014. hr = E_FAIL;
  1015. pIRiffStream->Ascend( &ck, 0 );
  1016. goto ON_END;
  1017. }
  1018. // now that the chord list is complete, transfer the pointers into the
  1019. // chord db (back to front to reinstate original order)
  1020. apChordDB = new DMExtendedChord*[nCount];
  1021. if (apChordDB)
  1022. {
  1023. TListItem<DMExtendedChord*>* pScan = ChordList.GetHead();
  1024. for (n = nCount - 1; n >= 0; n--)
  1025. {
  1026. apChordDB[n] = pScan->GetItemValue();
  1027. pScan = pScan->GetNext();
  1028. }
  1029. }
  1030. else
  1031. {
  1032. hr = E_OUTOFMEMORY;
  1033. pIRiffStream->Ascend( &ck, 0 );
  1034. goto ON_END;
  1035. }
  1036. break;
  1037. }
  1038. case FOURCC_LIST:
  1039. ck1 = ck;
  1040. ckList = ck;
  1041. switch( ck1.fccType )
  1042. {
  1043. case DMUS_FOURCC_CHORDPALETTE_LIST:
  1044. for( n = 0; pIRiffStream->Descend( &ck1, &ckList, 0 ) == 0 && n < 24; n++ )
  1045. {
  1046. if ( ck1.ckid == FOURCC_LIST && ck1.fccType == DMUS_FOURCC_CHORD_LIST )
  1047. {
  1048. TListItem<DMChordData>* pChordData = new TListItem<DMChordData>;
  1049. if (pChordData)
  1050. {
  1051. m_PersonalityInfo.m_aChordPalette[n].AddHead(pChordData);
  1052. hr = pChordData->GetItemValue().Read(pIRiffStream, &ck1, apChordDB);
  1053. }
  1054. }
  1055. pIRiffStream->Ascend( &ck1, 0 );
  1056. dwPos = StreamTell( pIStream );
  1057. }
  1058. break;
  1059. case DMUS_FOURCC_CHORDMAP_LIST:
  1060. {
  1061. short nMapMax = 0;
  1062. while ( pIRiffStream->Descend( &ck1, &ckList, 0 ) == 0 )
  1063. {
  1064. if ( ck1.ckid == FOURCC_LIST && ck1.fccType == DMUS_FOURCC_CHORDENTRY_LIST )
  1065. {
  1066. DM_LoadChordEntry(pIRiffStream, &ck1, apChordDB, nMapMax);
  1067. }
  1068. pIRiffStream->Ascend( &ck1, 0 );
  1069. dwPos = StreamTell( pIStream );
  1070. }
  1071. TListItem<DMChordEntry>** aChordArray = new TListItem<DMChordEntry>*[nMapMax + 1];
  1072. if (!aChordArray)
  1073. {
  1074. hr = E_OUTOFMEMORY;
  1075. pIRiffStream->Ascend( &ck, 0 );
  1076. goto ON_END;
  1077. }
  1078. TListItem<DMChordEntry>* pScan = m_PersonalityInfo.m_ChordMap.GetHead();
  1079. for(; pScan; pScan = pScan->GetNext())
  1080. {
  1081. if (pScan->GetItemValue().m_nID < 0 || pScan->GetItemValue().m_nID > nMapMax)
  1082. {
  1083. // the connection id was not properly initialized
  1084. Trace(1, "ERROR: Load (chord map): DMUS_FOURCC_CHORDMAP_LIST chunk contains an improperly initialized connection ID.\n");
  1085. hr = DMUS_E_NOT_INIT;
  1086. pIRiffStream->Ascend( &ck, 0 );
  1087. delete [] aChordArray;
  1088. goto ON_END;
  1089. }
  1090. aChordArray[pScan->GetItemValue().m_nID] = pScan;
  1091. }
  1092. pScan = m_PersonalityInfo.m_ChordMap.GetHead();
  1093. for (; pScan; pScan = pScan->GetNext())
  1094. {
  1095. TListItem<DMChordLink>* pLink = pScan->GetItemValue().m_Links.GetHead();
  1096. for (; pLink; pLink = pLink->GetNext())
  1097. {
  1098. DMChordLink& rLink = pLink->GetItemValue();
  1099. if (rLink.m_nID < 0 || rLink.m_nID > nMapMax)
  1100. {
  1101. // the connection id was not properly initialized
  1102. Trace(1, "ERROR: Load (chord map): DMUS_FOURCC_CHORDMAP_LIST chunk contains an improperly initialized connection ID.\n");
  1103. hr = DMUS_E_NOT_INIT;
  1104. pIRiffStream->Ascend( &ck, 0 );
  1105. delete [] aChordArray;
  1106. goto ON_END;
  1107. }
  1108. rLink.m_pChord = aChordArray[rLink.m_nID];
  1109. }
  1110. }
  1111. delete [] aChordArray;
  1112. break;
  1113. }
  1114. case DMUS_FOURCC_SIGNPOST_LIST:
  1115. while ( pIRiffStream->Descend( &ck1, &ckList, 0 ) == 0 )
  1116. {
  1117. if ( ck1.ckid == FOURCC_LIST && ck1.fccType == DMUS_FOURCC_SIGNPOSTITEM_LIST )
  1118. {
  1119. DM_LoadSignPost(pIRiffStream, &ck1, apChordDB);
  1120. }
  1121. pIRiffStream->Ascend( &ck1, 0 );
  1122. dwPos = StreamTell( pIStream );
  1123. }
  1124. break;
  1125. }
  1126. break;
  1127. }
  1128. pIRiffStream->Ascend( &ck, 0 );
  1129. dwPos = StreamTell( pIStream );
  1130. }
  1131. ON_END:
  1132. if (apChordDB) delete [] apChordDB;
  1133. pIStream->Release();
  1134. return hr;
  1135. }
  1136. HRESULT CDMPers::DM_LoadChordEntry(
  1137. IAARIFFStream* pIRiffStream, MMCKINFO* pckParent, DMExtendedChord** apChordDB, short& nMax )
  1138. {
  1139. HRESULT hr = S_OK;
  1140. if (!pIRiffStream || !pckParent) return E_INVALIDARG;
  1141. MMCKINFO ck;
  1142. IStream* pIStream = pIRiffStream->GetStream();
  1143. if(!pIStream) return E_FAIL;
  1144. WORD wConnectionID = 0;
  1145. TListItem<DMChordEntry>* pChordEntry = new TListItem<DMChordEntry>;
  1146. if (!pChordEntry) return E_OUTOFMEMORY;
  1147. DMChordEntry& rChordEntry = pChordEntry->GetItemValue();
  1148. rChordEntry.m_ChordData.m_strName = "";
  1149. m_PersonalityInfo.m_ChordMap.AddHead(pChordEntry);
  1150. while(pIRiffStream->Descend(&ck, pckParent, 0) == 0 && hr == S_OK)
  1151. {
  1152. switch(ck.ckid)
  1153. {
  1154. case DMUS_FOURCC_CHORDENTRY_CHUNK:
  1155. {
  1156. DMUS_IO_CHORDENTRY iChordEntry;
  1157. DWORD cb;
  1158. hr = pIStream->Read( &iChordEntry, sizeof(iChordEntry), &cb );
  1159. if (FAILED(hr) || cb != sizeof(iChordEntry) )
  1160. {
  1161. if (SUCCEEDED(hr)) hr = E_FAIL;
  1162. pIRiffStream->Ascend( &ck, 0 );
  1163. goto ON_END;
  1164. }
  1165. rChordEntry.m_dwFlags = iChordEntry.dwFlags;
  1166. rChordEntry.m_nID = iChordEntry.wConnectionID;
  1167. if (rChordEntry.m_nID > nMax) nMax = rChordEntry.m_nID;
  1168. }
  1169. break;
  1170. case FOURCC_LIST:
  1171. if (ck.fccType == DMUS_FOURCC_CHORD_LIST)
  1172. {
  1173. hr = rChordEntry.m_ChordData.Read(pIRiffStream, &ck, apChordDB);
  1174. }
  1175. break;
  1176. case DMUS_FOURCC_NEXTCHORDSEQ_CHUNK:
  1177. {
  1178. long lFileSize = ck.cksize;
  1179. WORD wSize;
  1180. DWORD cb;
  1181. hr = pIStream->Read( &wSize, sizeof( wSize ), &cb );
  1182. if (FAILED(hr) || cb != sizeof( wSize ) )
  1183. {
  1184. if (SUCCEEDED(hr)) hr = E_FAIL;
  1185. pIRiffStream->Ascend( &ck, 0 );
  1186. goto ON_END;
  1187. }
  1188. lFileSize -= cb;
  1189. while (lFileSize > 0)
  1190. {
  1191. DMUS_IO_NEXTCHORD iNextChord;
  1192. hr = pIStream->Read( &iNextChord, wSize, &cb );
  1193. if (FAILED(hr) || cb != wSize )
  1194. {
  1195. if (SUCCEEDED(hr)) hr = E_FAIL;
  1196. pIRiffStream->Ascend( &ck, 0 );
  1197. goto ON_END;
  1198. }
  1199. if (iNextChord.wConnectionID)
  1200. {
  1201. TListItem<DMChordLink>* pItem = new TListItem<DMChordLink>;
  1202. if (!pItem )
  1203. {
  1204. hr = E_OUTOFMEMORY;
  1205. pIRiffStream->Ascend( &ck, 0 );
  1206. goto ON_END;
  1207. }
  1208. DMChordLink& rLink = pItem->GetItemValue();
  1209. rLink.m_dwFlags = iNextChord.dwFlags;
  1210. rLink.m_nID = iNextChord.wConnectionID;
  1211. rLink.m_wWeight = iNextChord.nWeight;
  1212. rLink.m_wMinBeats = iNextChord.wMinBeats;
  1213. rLink.m_wMaxBeats = iNextChord.wMaxBeats;
  1214. rChordEntry.m_Links.AddHead(pItem);
  1215. }
  1216. lFileSize -= wSize;
  1217. }
  1218. if (lFileSize != 0 )
  1219. {
  1220. hr = E_FAIL;
  1221. pIRiffStream->Ascend( &ck, 0 );
  1222. goto ON_END;
  1223. }
  1224. }
  1225. break;
  1226. }
  1227. pIRiffStream->Ascend(&ck, 0);
  1228. }
  1229. ON_END:
  1230. if (pIStream) pIStream->Release();
  1231. return hr;
  1232. }
  1233. HRESULT CDMPers::DM_LoadSignPost( IAARIFFStream* pIRiffStream, MMCKINFO* pckParent, DMExtendedChord** apChordDB )
  1234. {
  1235. HRESULT hr = S_OK;
  1236. if (!pIRiffStream || !pckParent) return E_INVALIDARG;
  1237. MMCKINFO ck;
  1238. IStream* pIStream = pIRiffStream->GetStream();
  1239. if(!pIStream) return E_FAIL;
  1240. TListItem<DMSignPost>* pSignPost = new TListItem<DMSignPost>;
  1241. if (!pSignPost) return E_OUTOFMEMORY;
  1242. DMSignPost& rSignPost = pSignPost->GetItemValue();
  1243. m_PersonalityInfo.m_SignPostList.AddTail(pSignPost);
  1244. while(pIRiffStream->Descend(&ck, pckParent, 0) == 0 && hr == S_OK)
  1245. {
  1246. switch(ck.ckid)
  1247. {
  1248. case DMUS_FOURCC_IOSIGNPOST_CHUNK:
  1249. {
  1250. DMUS_IO_PERS_SIGNPOST iSignPost;
  1251. DWORD cb;
  1252. hr = pIStream->Read( &iSignPost, sizeof(iSignPost), &cb );
  1253. if (FAILED(hr) || cb != sizeof(iSignPost) )
  1254. {
  1255. if (SUCCEEDED(hr)) hr = E_FAIL;
  1256. pIRiffStream->Ascend( &ck, 0 );
  1257. goto ON_END;
  1258. }
  1259. rSignPost.m_dwChords = iSignPost.dwChords;
  1260. rSignPost.m_dwFlags = iSignPost.dwFlags;
  1261. }
  1262. break;
  1263. case FOURCC_LIST:
  1264. switch(ck.fccType)
  1265. {
  1266. case DMUS_FOURCC_CHORD_LIST:
  1267. hr = rSignPost.m_ChordData.Read(pIRiffStream, &ck, apChordDB);
  1268. break;
  1269. case DMUS_FOURCC_CADENCE_LIST:
  1270. {
  1271. MMCKINFO ckCadence = ck;
  1272. MMCKINFO ck1 = ck;
  1273. for (short n = 0;
  1274. pIRiffStream->Descend(&ck1, &ckCadence, 0) == 0 && hr == S_OK && n < 2;
  1275. n++)
  1276. {
  1277. if (ck1.fccType == DMUS_FOURCC_CHORD_LIST)
  1278. {
  1279. short n2 = n;
  1280. if ( !(rSignPost.m_dwFlags & DMUS_SPOSTCADENCEF_1) &&
  1281. (rSignPost.m_dwFlags & DMUS_SPOSTCADENCEF_2) )
  1282. {
  1283. // if all we have is cadence 2, put it in location 1
  1284. n2 = 1;
  1285. }
  1286. hr = rSignPost.m_aCadence[n2].Read(pIRiffStream, &ck1, apChordDB);
  1287. }
  1288. pIRiffStream->Ascend(&ck1, 0);
  1289. }
  1290. }
  1291. break;
  1292. }
  1293. break;
  1294. }
  1295. pIRiffStream->Ascend(&ck, 0);
  1296. }
  1297. ON_END:
  1298. if (pIStream) pIStream->Release();
  1299. return hr;
  1300. }
  1301. HRESULT DMChordData::Read(
  1302. IAARIFFStream* pIRiffStream, MMCKINFO* pckParent, DMExtendedChord** apChordDB)
  1303. {
  1304. HRESULT hr1 = E_FAIL, hr2 = E_FAIL;
  1305. if (!pIRiffStream || !pckParent) return E_INVALIDARG;
  1306. if (!apChordDB) return E_POINTER;
  1307. MMCKINFO ck;
  1308. wchar_t wzName[12];
  1309. WORD awSubIds[4];
  1310. IStream* pIStream = pIRiffStream->GetStream();
  1311. if(!pIStream) return E_FAIL;
  1312. while(pIRiffStream->Descend(&ck, pckParent, 0) == 0)
  1313. {
  1314. TListItem<DMExtendedChord*>* pChord = NULL;
  1315. switch(ck.ckid)
  1316. {
  1317. case DMUS_FOURCC_CHORDNAME_CHUNK:
  1318. hr1 = pIStream->Read(wzName, sizeof(wzName), 0);
  1319. if (SUCCEEDED(hr1)) m_strName = wzName;
  1320. break;
  1321. case DMUS_FOURCC_SUBCHORDID_CHUNK:
  1322. hr2 = pIStream->Read(awSubIds, sizeof(awSubIds), 0);
  1323. // now use the ids to set up pointers to subchords
  1324. if (m_pSubChords) Release();
  1325. pChord = new TListItem<DMExtendedChord*>(apChordDB[awSubIds[3]]);
  1326. if (pChord)
  1327. {
  1328. pChord->GetItemValue()->AddRef();
  1329. for (short n = 2; n >= 0; n--)
  1330. {
  1331. TListItem<DMExtendedChord*>* pNew = new TListItem<DMExtendedChord*>(apChordDB[awSubIds[n]]);
  1332. if (pNew)
  1333. {
  1334. pNew->GetItemValue()->AddRef();
  1335. pNew->SetNext(pChord);
  1336. pChord = pNew;
  1337. }
  1338. }
  1339. }
  1340. m_pSubChords = pChord;
  1341. break;
  1342. }
  1343. pIRiffStream->Ascend(&ck, 0);
  1344. }
  1345. pIStream->Release();
  1346. return (hr1 == S_OK && hr2 == S_OK) ? S_OK : E_FAIL;
  1347. }