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.

529 lines
19 KiB

  1. // Copyright (c) 1998-1999 Microsoft Corporation
  2. // WavTrack.h : Declaration of the CWavTrack
  3. #ifndef __WAVTRACK_H_
  4. #define __WAVTRACK_H_
  5. #include "dmusici.h"
  6. #include "dmusicf.h"
  7. #include "dmstrm.h"
  8. #include "tlist.h"
  9. #include "PChMap.h"
  10. #include "..\shared\dmusiccp.h"
  11. #include "dsoundp.h" // For IDirectSoundWave
  12. interface IPrivateWaveTrack : IUnknown
  13. {
  14. virtual HRESULT STDMETHODCALLTYPE SetVariation(
  15. IDirectMusicSegmentState* pSegState,
  16. DWORD dwVariationFlags,
  17. DWORD dwPChannel,
  18. DWORD dwIndex)=0;
  19. virtual HRESULT STDMETHODCALLTYPE ClearVariations(IDirectMusicSegmentState* pSegState)=0;
  20. virtual HRESULT STDMETHODCALLTYPE AddWave(
  21. IDirectSoundWave* pWave,
  22. REFERENCE_TIME rtTime,
  23. DWORD dwPChannel,
  24. DWORD dwIndex,
  25. REFERENCE_TIME* prtLength)=0;
  26. virtual HRESULT STDMETHODCALLTYPE DownloadWave(
  27. IDirectSoundWave* pWave, // wave to download
  28. IUnknown* pUnk, // performance or audio path
  29. REFGUID rguidVersion)=0; // version of downloaded wave
  30. virtual HRESULT STDMETHODCALLTYPE UnloadWave(
  31. IDirectSoundWave* pWave, // wave to unload
  32. IUnknown* pUnk)=0; // performance or audio path
  33. virtual HRESULT STDMETHODCALLTYPE RefreshWave(
  34. IDirectSoundWave* pWave, // wave to refresh
  35. IUnknown* pUnk, // performance or audio path
  36. DWORD dwPChannel, // new PChannel for the wave
  37. REFGUID rguidVersion)=0; // version of refreshed wave
  38. virtual HRESULT STDMETHODCALLTYPE FlushAllWaves()=0;
  39. virtual HRESULT STDMETHODCALLTYPE OnVoiceEnd(IDirectMusicVoiceP *pVoice, void *pStateData)=0;
  40. };
  41. DEFINE_GUID(IID_IPrivateWaveTrack, 0x492abe2a, 0x38c8, 0x48a3, 0x8f, 0x3c, 0x1e, 0x13, 0xba, 0x1, 0x78, 0x4e);
  42. const int MAX_WAVE_VARIATION_LOCKS = 255; // max number of variation lock ids
  43. struct TaggedWave
  44. {
  45. IDirectSoundWave* m_pWave;
  46. GUID m_guidVersion;
  47. IDirectSoundDownloadedWaveP* m_pDownloadedWave;
  48. long m_lRefCount;
  49. IDirectMusicPortP* m_pPort;
  50. IDirectMusicPerformance* m_pPerformance;
  51. TaggedWave() : m_pWave(NULL), m_pDownloadedWave(NULL), m_lRefCount(0),
  52. m_pPort(NULL), m_pPerformance(NULL), m_guidVersion(GUID_NULL)
  53. {
  54. }
  55. ~TaggedWave()
  56. {
  57. if (m_pWave) m_pWave->Release();
  58. if (m_pPort) m_pPort->Release();
  59. if (m_pPerformance) m_pPerformance->Release();
  60. if (m_pDownloadedWave) m_pDownloadedWave->Release();
  61. }
  62. };
  63. struct WaveItem
  64. {
  65. WaveItem() : m_rtTimePhysical(0), m_lVolume(0), m_lPitch(0), m_dwVariations(0),
  66. m_rtStartOffset(0), m_rtDuration(0), m_mtTimeLogical(0), m_dwFlags(0),
  67. m_pWave(NULL), m_dwLoopStart(0), m_dwLoopEnd(0), m_dwVoiceIndex(0xffffffff),
  68. m_pDownloadedWave(NULL), m_fIsStreaming(FALSE), m_fUseNoPreRoll(FALSE)
  69. {
  70. }
  71. ~WaveItem()
  72. {
  73. CleanUp();
  74. }
  75. HRESULT Load( IDMStream* pIRiffStream, MMCKINFO* pckParent );
  76. HRESULT LoadReference(IStream *pStream, IDMStream *pIRiffStream, MMCKINFO& ckParent);
  77. HRESULT Download(IDirectMusicPerformance* pPerformance,
  78. IDirectMusicAudioPath* pPath,
  79. DWORD dwPChannel,
  80. IDirectSoundWave* pWave,
  81. REFGUID rguidVersion);
  82. HRESULT Unload(IDirectMusicPerformance* pPerformance,
  83. IDirectMusicAudioPath* pPath,
  84. DWORD dwPChannel,
  85. IDirectSoundWave* pWave);
  86. HRESULT Refresh(IDirectMusicPerformance* pPerformance,
  87. IDirectMusicAudioPath* pPath,
  88. DWORD dwOldPChannel,
  89. DWORD dwNewPChannel,
  90. IDirectSoundWave* pWave,
  91. REFGUID rguidVersion);
  92. static HRESULT PChannelInfo(
  93. IDirectMusicPerformance* pPerformance,
  94. IDirectMusicAudioPath* pAudioPath,
  95. DWORD dwPChannel,
  96. IDirectMusicPort** ppPort,
  97. DWORD* pdwGroup,
  98. DWORD* pdwMChannel);
  99. void CleanUp();
  100. HRESULT Add(IDirectSoundWave* pWave, REFERENCE_TIME rtTime, REFERENCE_TIME* prtLength);
  101. REFERENCE_TIME m_rtTimePhysical;
  102. long m_lVolume;
  103. long m_lPitch;
  104. DWORD m_dwVariations; // variations this wave item responds to
  105. REFERENCE_TIME m_rtStartOffset;
  106. REFERENCE_TIME m_rtDuration;
  107. MUSIC_TIME m_mtTimeLogical;
  108. DWORD m_dwFlags;
  109. IDirectSoundWave* m_pWave;
  110. IDirectSoundDownloadedWaveP* m_pDownloadedWave;
  111. BOOL m_fIsStreaming;
  112. BOOL m_fUseNoPreRoll;
  113. DWORD m_dwLoopStart;
  114. DWORD m_dwLoopEnd;
  115. DWORD m_dwVoiceIndex; // unique (to the track) index for state data's vaoice array
  116. static TList<TaggedWave> st_WaveList;
  117. static CRITICAL_SECTION st_WaveListCritSect;
  118. };
  119. struct WavePart
  120. {
  121. WavePart() : m_dwPChannel(0), m_lVolume(0), m_dwLockToPart(0),
  122. m_dwPChannelFlags(0), m_dwVariations(0), m_dwIndex(0)
  123. {
  124. }
  125. ~WavePart()
  126. {
  127. CleanUp();
  128. }
  129. HRESULT Load( IDMStream* pIRiffStream, MMCKINFO* pckParent );
  130. HRESULT CopyItems( const TList<WaveItem>& rItems, MUSIC_TIME mtStart, MUSIC_TIME mtEnd );
  131. void CleanUp();
  132. HRESULT Download(IDirectMusicPerformance* pPerformance,
  133. IDirectMusicAudioPath* pPath,
  134. IDirectSoundWave* pWave,
  135. REFGUID rguidVersion);
  136. HRESULT Unload(IDirectMusicPerformance* pPerformance,
  137. IDirectMusicAudioPath* pPath,
  138. IDirectSoundWave* pWave);
  139. HRESULT Refresh(IDirectMusicPerformance* pPerformance,
  140. IDirectMusicAudioPath* pPath,
  141. IDirectSoundWave* pWave,
  142. DWORD dwPChannel,
  143. REFGUID rguidVersion);
  144. HRESULT Add(
  145. IDirectSoundWave* pWave,
  146. REFERENCE_TIME rtTime,
  147. DWORD dwPChannel,
  148. DWORD dwIndex,
  149. REFERENCE_TIME* prtLength);
  150. DWORD m_dwPChannel;
  151. DWORD m_dwIndex; // Index to distinguish different parts on the same PChannel
  152. DWORD m_lVolume;
  153. DWORD m_dwVariations; // variations enabled for this part
  154. DWORD m_dwLockToPart; // all parts with this ID are locked (0 means no locking)
  155. DWORD m_dwPChannelFlags; // lowest-order nibble holds DMUS_VARIATIONT_TYPES value
  156. TList<WaveItem> m_WaveItemList;
  157. };
  158. struct WaveDLOnPlay
  159. {
  160. WaveDLOnPlay() : m_pWaveDL(NULL), m_pPort(NULL), m_pVoice(NULL) {}
  161. ~WaveDLOnPlay()
  162. {
  163. if (m_pPort)
  164. {
  165. if (m_pWaveDL)
  166. {
  167. m_pPort->UnloadWave(m_pWaveDL);
  168. }
  169. m_pWaveDL = NULL;
  170. m_pPort->Release();
  171. m_pPort = NULL;
  172. }
  173. if (m_pVoice)
  174. {
  175. m_pVoice->Release();
  176. m_pVoice = NULL;
  177. }
  178. }
  179. IDirectSoundDownloadedWaveP* m_pWaveDL;
  180. IDirectMusicPortP* m_pPort;
  181. IDirectMusicVoiceP* m_pVoice;
  182. };
  183. struct WaveStateData
  184. {
  185. DWORD dwPChannelsUsed; // number of PChannels
  186. // the following array is allocated to the size of dwNumPChannels, which
  187. // must match the Wave Track's m_dwPChannelsUsed. The array matches one-for-one with
  188. // the parts inside the Wave Track.
  189. TListItem<WaveItem>** apCurrentWave; // array of size dwNumPChannels
  190. DWORD dwValidate;
  191. DWORD dwGroupBits; // the group bits of this track
  192. DWORD* pdwVariations; // array of variations (1 per part)
  193. DWORD* pdwRemoveVariations; // array of variations already played (1 per part)
  194. DWORD adwVariationGroups[MAX_WAVE_VARIATION_LOCKS];
  195. REFERENCE_TIME rtNextVariation; // time of next variation
  196. DWORD m_dwVariation; // selected variations to audition
  197. DWORD m_dwPart; // PChannel of part for auditioning variations
  198. DWORD m_dwIndex; // Index of part for auditioning variations
  199. DWORD m_dwLockID; // For locking to the part being auditioned
  200. BOOL m_fAudition; // Am I auditioning variations?
  201. IDirectMusicPerformance* m_pPerformance;
  202. IDirectMusicVoiceP** m_apVoice; // array of voices (one per wave item in track)
  203. DWORD m_dwVoices; // number of voices in m_apVoice
  204. bool m_fLoop; // set after the wave loops
  205. IDirectMusicAudioPath* m_pAudioPath; // audio path in effect for this track state
  206. TList<WaveDLOnPlay> m_WaveDLList; // waves downloaded while the track was playing
  207. WaveStateData() : dwPChannelsUsed(0), apCurrentWave(NULL), dwGroupBits(0),
  208. pdwVariations(NULL), pdwRemoveVariations(NULL), rtNextVariation(0),
  209. m_dwVariation(0), m_dwPart(0), m_dwIndex(0), m_dwLockID(0), m_fAudition(FALSE),
  210. m_pPerformance(NULL), m_apVoice(NULL), m_dwVoices(0), m_fLoop(false), m_pAudioPath(NULL)
  211. {
  212. for (int i = 0; i < MAX_WAVE_VARIATION_LOCKS; i++)
  213. {
  214. adwVariationGroups[i] = 0;
  215. }
  216. }
  217. ~WaveStateData()
  218. {
  219. if( apCurrentWave )
  220. {
  221. delete [] apCurrentWave;
  222. }
  223. if( pdwVariations )
  224. {
  225. delete [] pdwVariations;
  226. }
  227. if( pdwRemoveVariations )
  228. {
  229. delete [] pdwRemoveVariations;
  230. }
  231. if (m_apVoice)
  232. {
  233. for (DWORD dw = 0; dw < m_dwVoices; dw++)
  234. {
  235. if (m_apVoice[dw])
  236. {
  237. m_apVoice[dw]->Release();
  238. }
  239. }
  240. delete [] m_apVoice;
  241. }
  242. if( m_pAudioPath )
  243. {
  244. m_pAudioPath->Release();
  245. }
  246. TListItem<WaveDLOnPlay>* pWDLOnPlay = NULL;
  247. while (!m_WaveDLList.IsEmpty())
  248. {
  249. pWDLOnPlay = m_WaveDLList.RemoveHead();
  250. delete pWDLOnPlay;
  251. }
  252. }
  253. HRESULT InitVariationInfo(DWORD dwVariations, DWORD dwPart, DWORD dwIndex, DWORD dwLockID, BOOL fAudition)
  254. {
  255. HRESULT hr = S_OK;
  256. m_dwVariation = dwVariations;
  257. m_dwPart = dwPart;
  258. m_dwIndex = dwIndex;
  259. m_dwLockID = dwLockID;
  260. m_fAudition = fAudition;
  261. return hr;
  262. }
  263. DWORD Variations(WavePart& rPart, int nPartIndex)
  264. {
  265. if (m_dwLockID && rPart.m_dwLockToPart == m_dwLockID)
  266. {
  267. TraceI(4, "Variations for locked part\n");
  268. return m_dwVariation;
  269. }
  270. else if ( m_fAudition &&
  271. (rPart.m_dwPChannel == m_dwPart) &&
  272. (rPart.m_dwIndex == m_dwIndex) )
  273. {
  274. TraceI(4, "Variations for current part\n");
  275. return m_dwVariation;
  276. }
  277. else
  278. {
  279. TraceI(4, "Variations for a different part\n");
  280. return pdwVariations[nPartIndex];
  281. }
  282. }
  283. };
  284. struct StatePair
  285. {
  286. StatePair() : m_pSegState(NULL), m_pStateData(NULL) {}
  287. StatePair(const StatePair& rPair)
  288. {
  289. m_pSegState = rPair.m_pSegState;
  290. m_pStateData = rPair.m_pStateData;
  291. }
  292. StatePair(IDirectMusicSegmentState* pSegState, WaveStateData* pStateData)
  293. {
  294. m_pSegState = pSegState;
  295. m_pStateData = pStateData;
  296. }
  297. StatePair& operator= (const StatePair& rPair)
  298. {
  299. if (this != &rPair)
  300. {
  301. m_pSegState = rPair.m_pSegState;
  302. m_pStateData = rPair.m_pStateData;
  303. }
  304. return *this;
  305. }
  306. ~StatePair()
  307. {
  308. }
  309. IDirectMusicSegmentState* m_pSegState;
  310. WaveStateData* m_pStateData;
  311. };
  312. struct WavePair
  313. {
  314. WavePair() : m_pWaveDL(NULL), m_pStateData(NULL) {}
  315. ~WavePair()
  316. {
  317. if (m_pWaveDL) m_pWaveDL->Release();
  318. }
  319. IDirectSoundDownloadedWaveP* m_pWaveDL;
  320. WaveStateData* m_pStateData;
  321. };
  322. /////////////////////////////////////////////////////////////////////////////
  323. // CWavTrack
  324. class CWavTrack :
  325. public IPersistStream,
  326. public IDirectMusicTrack8,
  327. public IPrivateWaveTrack
  328. {
  329. public:
  330. CWavTrack();
  331. CWavTrack(const CWavTrack& rTrack, MUSIC_TIME mtStart, MUSIC_TIME mtEnd);
  332. ~CWavTrack();
  333. public:
  334. // IUnknown
  335. STDMETHODIMP QueryInterface(const IID &iid, void **ppv);
  336. STDMETHODIMP_(ULONG) AddRef();
  337. STDMETHODIMP_(ULONG) Release();
  338. // IDirectMusicTrack methods
  339. STDMETHODIMP IsParamSupported(REFGUID rguid);
  340. STDMETHODIMP Init(IDirectMusicSegment *pSegment);
  341. STDMETHODIMP InitPlay(IDirectMusicSegmentState *pSegmentState,
  342. IDirectMusicPerformance *pPerformance,
  343. void **ppStateData,
  344. DWORD dwTrackID,
  345. DWORD dwFlags);
  346. STDMETHODIMP EndPlay(void *pStateData);
  347. STDMETHODIMP Play(void *pStateData,MUSIC_TIME mtStart,
  348. MUSIC_TIME mtEnd,MUSIC_TIME mtOffset,
  349. DWORD dwFlags,IDirectMusicPerformance* pPerf,
  350. IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID);
  351. STDMETHODIMP GetParam(REFGUID rguid,MUSIC_TIME mtTime,MUSIC_TIME* pmtNext,void *pData);
  352. STDMETHODIMP SetParam(REFGUID rguid,MUSIC_TIME mtTime,void *pData);
  353. STDMETHODIMP AddNotificationType(REFGUID rguidNotification);
  354. STDMETHODIMP RemoveNotificationType(REFGUID rguidNotification);
  355. STDMETHODIMP Clone(MUSIC_TIME mtStart,MUSIC_TIME mtEnd,IDirectMusicTrack** ppTrack);
  356. // IDirectMusicTrack8 methods
  357. STDMETHODIMP PlayEx(void* pStateData,REFERENCE_TIME rtStart,
  358. REFERENCE_TIME rtEnd,REFERENCE_TIME rtOffset,
  359. DWORD dwFlags,IDirectMusicPerformance* pPerf,
  360. IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID) ;
  361. STDMETHODIMP GetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
  362. REFERENCE_TIME* prtNext,void* pParam,void * pStateData, DWORD dwFlags) ;
  363. STDMETHODIMP SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,void* pParam, void * pStateData, DWORD dwFlags) ;
  364. STDMETHODIMP Compose(IUnknown* pContext,
  365. DWORD dwTrackGroup,
  366. IDirectMusicTrack** ppResultTrack) ;
  367. STDMETHODIMP Join(IDirectMusicTrack* pNewTrack,
  368. MUSIC_TIME mtJoin,
  369. IUnknown* pContext,
  370. DWORD dwTrackGroup,
  371. IDirectMusicTrack** ppResultTrack) ;
  372. // IPersist methods
  373. STDMETHODIMP GetClassID( CLSID* pClsId );
  374. // IPersistStream methods
  375. STDMETHODIMP IsDirty();
  376. STDMETHODIMP Load( IStream* pIStream );
  377. STDMETHODIMP Save( IStream* pIStream, BOOL fClearDirty );
  378. STDMETHODIMP GetSizeMax( ULARGE_INTEGER FAR* pcbSize );
  379. // IPrivateWaveTrack methods
  380. STDMETHODIMP SetVariation(
  381. IDirectMusicSegmentState* pSegState,
  382. DWORD dwVariationFlags,
  383. DWORD dwPChannel,
  384. DWORD dwIndex);
  385. STDMETHODIMP ClearVariations(IDirectMusicSegmentState* pSegState);
  386. STDMETHODIMP AddWave(
  387. IDirectSoundWave* pWave,
  388. REFERENCE_TIME rtTime,
  389. DWORD dwPChannel,
  390. DWORD dwIndex,
  391. REFERENCE_TIME* prtLength);
  392. STDMETHODIMP DownloadWave(
  393. IDirectSoundWave* pWave,
  394. IUnknown* pUnk,
  395. REFGUID rguidVersion);
  396. STDMETHODIMP UnloadWave(
  397. IDirectSoundWave* pWave,
  398. IUnknown* pUnk);
  399. STDMETHODIMP RefreshWave(
  400. IDirectSoundWave* pWave,
  401. IUnknown* pUnk,
  402. DWORD dwPChannel,
  403. REFGUID rguidVersion);
  404. STDMETHODIMP FlushAllWaves();
  405. STDMETHODIMP OnVoiceEnd(IDirectMusicVoiceP *pVoice, void *pStateData);
  406. // misc
  407. static HRESULT UnloadAllWaves(IDirectMusicPerformance* pPerformance);
  408. protected:
  409. void Construct(void);
  410. HRESULT Play(
  411. void *pStateData,
  412. REFERENCE_TIME rtStart,
  413. REFERENCE_TIME rtEnd,
  414. // MUSIC_TIME mtOffset,
  415. REFERENCE_TIME rtOffset,
  416. DWORD dwFlags,
  417. IDirectMusicPerformance* pPerf,
  418. IDirectMusicSegmentState* pSegSt,
  419. DWORD dwVirtualID,
  420. BOOL fClockTime);
  421. void InsertByAscendingPChannel( TListItem<WavePart>* pPart );
  422. HRESULT CopyParts( const TList<WavePart>& rParts, MUSIC_TIME mtStart, MUSIC_TIME mtEnd );
  423. void CleanUp();
  424. void CleanUpTempParts();
  425. void MovePartsToTemp();
  426. IDirectSoundDownloadedWaveP* FindDownload(TListItem<WaveItem>* pItem);
  427. void SetUpStateCurrentPointers(WaveStateData* pStateData);
  428. HRESULT STDMETHODCALLTYPE Seek(
  429. IDirectMusicSegmentState*,
  430. IDirectMusicPerformance*,
  431. DWORD dwVirtualID,
  432. WaveStateData*,
  433. REFERENCE_TIME rtTime,
  434. BOOL fGetPrevious,
  435. // MUSIC_TIME mtOffset,
  436. REFERENCE_TIME rtOffset,
  437. BOOL fClockTime);
  438. HRESULT SyncVariations(IDirectMusicPerformance* pPerf,
  439. WaveStateData* pSD,
  440. REFERENCE_TIME rtStart,
  441. REFERENCE_TIME rtOffset,
  442. BOOL fClockTime);
  443. HRESULT ComputeVariations(WaveStateData* pSD);
  444. HRESULT ComputeVariation(int nPart, WavePart& rWavePart, WaveStateData* pSD);
  445. WaveStateData* FindState(IDirectMusicSegmentState* pSegState);
  446. HRESULT InitTrack(DWORD dwPChannels);
  447. HRESULT GetDownload(
  448. IDirectSoundDownloadedWaveP* pWaveDL,
  449. WaveStateData* pStateData,
  450. IDirectMusicPortP* pPortP,
  451. IDirectSoundWave* pWave,
  452. REFERENCE_TIME rtStartOffset,
  453. WaveItem& rItem,
  454. DWORD dwMChannel,
  455. DWORD dwGroup,
  456. IDirectMusicVoiceP **ppVoice);
  457. void RemoveDownloads(WaveStateData* pStateData);
  458. static void FlushWaves();
  459. // member variables
  460. private:
  461. long m_cRef;
  462. CRITICAL_SECTION m_CrSec;
  463. BOOL m_fCSInitialized;
  464. long m_lVolume;
  465. DWORD m_dwTrackFlags; // Only current flag is DMUS_WAVETRACKF_SYNC_VAR
  466. DWORD m_dwPChannelsUsed;
  467. DWORD* m_aPChannels;
  468. TList<WavePart> m_WavePartList;
  469. TList<WavePart> m_TempWavePartList; // keep this around when reloading the track
  470. DWORD m_dwValidate; // used to validate state data
  471. CPChMap m_PChMap;
  472. DWORD m_dwVariation; // selected variations to audition
  473. DWORD m_dwPart; // PChannel of part for auditioning variations
  474. DWORD m_dwIndex; // Index of part for auditioning variations
  475. DWORD m_dwLockID; // For locking to the part being auditioned
  476. BOOL m_fAudition; // Am I auditioning variations?
  477. BOOL m_fAutoDownload;
  478. BOOL m_fLockAutoDownload; // if true, this flag indicates that we've specifically
  479. // commanded the band to autodownload. Otherwise,
  480. // it gets its preference from the performance via
  481. // GetGlobalParam.
  482. DWORD* m_pdwVariations; // Track's array of variations (1 per part)
  483. DWORD* m_pdwRemoveVariations; // Track's array of variations already played (1 per part)
  484. DWORD m_dwWaveItems; // Total number of wave items in the track
  485. TList<StatePair> m_StateList; // The track's state information
  486. TList<WavePair> m_WaveList; // Information about waves downloaded to the track
  487. static long st_RefCount; // global count of # of instantiated wave tracks
  488. };
  489. #endif //__WAVTRACK_H_