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.

684 lines
31 KiB

  1. // Copyright (c) 1998-1999 Microsoft Corporation
  2. // dmperf.h
  3. // @doc EXTERNAL
  4. #ifndef _DMPERF_H_
  5. #define _DMPERF_H_
  6. #if _MSC_VER >= 1000
  7. #pragma once
  8. #endif // _MSC_VER >= 1000
  9. #include "dmusicc.h"
  10. #include "dmusici.h"
  11. #include "dmusicf.h"
  12. #include "dmime.h"
  13. #include "ntfylist.h"
  14. #include "dmsstobj.h"
  15. #include "audpath.h"
  16. #include "..\shared\dmusicp.h"
  17. #define DMUS_PCHANNEL_KILL_ME 0xFFFFFFF0
  18. typedef struct _DMUS_SEGSTATEDATA
  19. {
  20. _DMUS_SEGSTATEDATA * pNext; // Linked list of these.
  21. DWORD dwQueue; // Which queue it is in.
  22. WCHAR wszName[DMUS_MAX_NAME]; // Name of object.
  23. MUSIC_TIME mtLoopStart; // Loop start point.
  24. MUSIC_TIME mtLoopEnd; // Loop end point.
  25. DWORD dwRepeats; // The original repeat setting (before countdown)
  26. MUSIC_TIME mtLength; // Length of segment.
  27. REFERENCE_TIME rtGivenStart; // Start time given in PlaySegment, unquantized
  28. MUSIC_TIME mtResolvedStart;// Start time resolved to desired resolution
  29. MUSIC_TIME mtOffset; // Start time of the segment in absolute time, as if it were started from the beginning.
  30. MUSIC_TIME mtLastPlayed; // The last played absolute time
  31. MUSIC_TIME mtPlayTo; // Used to stop play at a specific time. Ignored when 0.
  32. MUSIC_TIME mtSeek; // How far into the segment we are.
  33. MUSIC_TIME mtStartPoint; // Point in the segment where playback started
  34. DWORD dwRepeatsLeft;// Current repeats left.
  35. DWORD dwPlayFlags;// Segment playback control flags
  36. BOOL fStartedPlay; // Indicates if the segstate has started to play yet
  37. IDirectMusicSegmentState *pSegState; // Pointer to segstate.
  38. } DMUS_SEGSTATEDATA;
  39. /*////////////////////////////////////////////////////////////////////
  40. // IDirectMusicParamHook */
  41. #undef INTERFACE
  42. #define INTERFACE IDirectMusicParamHook
  43. DECLARE_INTERFACE_(IDirectMusicParamHook, IUnknown)
  44. {
  45. /* IUnknown */
  46. STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE;
  47. STDMETHOD_(ULONG,AddRef) (THIS) PURE;
  48. STDMETHOD_(ULONG,Release) (THIS) PURE;
  49. /* IDirectMusicParamHook */
  50. STDMETHOD(GetParam) (THIS_ REFGUID rguidType,
  51. DWORD dwGroupBits,
  52. DWORD dwIndex,
  53. MUSIC_TIME mtTime,
  54. MUSIC_TIME* pmtNext,
  55. void* pData,
  56. IDirectMusicSegmentState *pSegState,
  57. DWORD dwTrackFlags,
  58. HRESULT hr) PURE;
  59. };
  60. #undef INTERFACE
  61. #define INTERFACE IDirectMusicSetParamHook
  62. DECLARE_INTERFACE_(IDirectMusicSetParamHook, IUnknown)
  63. {
  64. /* IUnknown */
  65. STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE;
  66. STDMETHOD_(ULONG,AddRef) (THIS) PURE;
  67. STDMETHOD_(ULONG,Release) (THIS) PURE;
  68. /* IDirectMusicSetParamHook */
  69. STDMETHOD(SetParamHook) (THIS_ IDirectMusicParamHook *pIHook) PURE;
  70. };
  71. #undef INTERFACE
  72. #define INTERFACE IDirectMusicPerformanceStats
  73. DECLARE_INTERFACE_(IDirectMusicPerformanceStats, IUnknown)
  74. {
  75. /* IUnknown */
  76. STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE;
  77. STDMETHOD_(ULONG,AddRef) (THIS) PURE;
  78. STDMETHOD_(ULONG,Release) (THIS) PURE;
  79. /* IDirectMusicPerformanceStats */
  80. STDMETHOD(TraceAllSegments) (THIS) PURE;
  81. STDMETHOD(CreateSegstateList) (THIS_ DMUS_SEGSTATEDATA ** ppList) PURE;
  82. STDMETHOD(FreeSegstateList) (THIS_ DMUS_SEGSTATEDATA * pList) PURE;
  83. };
  84. #define DEFAULT_BUFFER_SIZE 1024
  85. // the following constants represent time in milliseconds
  86. #define TRANSPORT_RES 100
  87. #define REALTIME_RES 10
  88. // the following constants represent time in 100 nanosecond increments
  89. #define REF_PER_MIL 10000 // For converting from reference time to mils
  90. #define MARGIN_MIN (100 * REF_PER_MIL) //
  91. #define MARGIN_MAX (400 * REF_PER_MIL) //
  92. #define PREPARE_TIME (m_dwPrepareTime * REF_PER_MIL) // Time
  93. #define NEARTIME (100 * REF_PER_MIL)
  94. #define NEARMARGIN (REALTIME_RES * REF_PER_MIL)
  95. /*
  96. // here's a convenience inline function that helps using resolution bits
  97. inline DWORD SIMPLIFY_RESOLUTION(DWORD x)
  98. {
  99. if( x & DMUS_SEGF_DEFAULT )
  100. {
  101. return DMUS_SEGF_DEFAULT;
  102. }
  103. else if( x & DMUS_SEGF_SEGMENTEND )
  104. {
  105. return DMUS_SEGF_SEGMENTEND;
  106. }
  107. else if( x & DMUS_SEGF_MARKER )
  108. {
  109. return DMUS_SEGF_MARKER;
  110. }
  111. else if( x & DMUS_SEGF_MEASURE )
  112. {
  113. return DMUS_SEGF_MEASURE;
  114. }
  115. else if( x & DMUS_SEGF_BEAT )
  116. {
  117. return DMUS_SEGF_BEAT;
  118. }
  119. else if( x & DMUS_SEGF_GRID )
  120. {
  121. return DMUS_SEGF_GRID;
  122. }
  123. else return 0;
  124. }
  125. */
  126. struct PRIV_PMSG;
  127. // pNext contains the next pointer for the next PMsg
  128. // dwPrivFlags contains private flags used by the performance
  129. // rtLast contains the previous time when an event is requeued,
  130. // which is used by the flush routine
  131. #define PRIV_PART \
  132. struct PRIV_PMSG* pNext; \
  133. DWORD dwPrivFlags; \
  134. DWORD dwPrivPubSize; \
  135. REFERENCE_TIME rtLast;
  136. typedef struct PRIV_PART_STRUCT
  137. {
  138. /* begin PRIV_PART */
  139. PRIV_PART
  140. /* end PRIV_PART */
  141. } PRIV_PART_STRUCT;
  142. #define PRIV_PART_SIZE sizeof(PRIV_PART_STRUCT)
  143. #define PRIV_TO_DMUS(x) ((DMUS_PMSG*)(LPBYTE(x) + PRIV_PART_SIZE))
  144. #define DMUS_TO_PRIV(x) ((PRIV_PMSG*)(LPBYTE(x) - PRIV_PART_SIZE))
  145. typedef struct PRIV_PMSG
  146. {
  147. /* begin PRIV_PART */
  148. PRIV_PART
  149. /* end PRIV_PART */
  150. /* begin DMUS_PMSG_PART */
  151. DMUS_PMSG_PART
  152. /* end DMUS_PMSG_PART */
  153. } PRIV_PMSG;
  154. typedef struct PRIV_TEMPO_PMSG
  155. {
  156. /* begin PRIV_PART */
  157. PRIV_PART
  158. /* end PRIV_PART */
  159. DMUS_TEMPO_PMSG tempoPMsg;
  160. } PRIV_TEMPO_PMSG;
  161. #define PRIV_FLAG_ALLOC_MASK 0x0000FFFF0 // using 4 bits for this for now
  162. #define PRIV_FLAG_ALLOC 0x0000CAFE0 // arbitrary pattern for allocated
  163. #define PRIV_FLAG_FREE 0x0000DEAD0 // pattern for in free list
  164. #define PRIV_FLAG_QUEUED 0x000000001 // set if in a queue
  165. #define PRIV_FLAG_REMOVE 0x000000002 // set if this needs to be removed from a queue
  166. #define PRIV_FLAG_TRACK 0x000000004 // indicates this message was generated by a track
  167. #define PRIV_FLAG_FLUSH 0x000000008 // this is a curve that needs to be flushed after
  168. // its end value has played
  169. #define PRIV_FLAG_REQUEUE 0x000100000 // set if this needs to be requeued to a queue
  170. class CPMsgQueue
  171. {
  172. public:
  173. CPMsgQueue();
  174. ~CPMsgQueue();
  175. void Enqueue(PRIV_PMSG *pItem);
  176. PRIV_PMSG * Dequeue();
  177. PRIV_PMSG * Dequeue(PRIV_PMSG *pItem);
  178. PRIV_PMSG * GetHead() { return (m_pTop);}
  179. PRIV_PMSG * FlushOldest(REFERENCE_TIME rtTime);
  180. long GetCount();
  181. void Sort();
  182. private:
  183. PRIV_PMSG * m_pTop; // Top of list.
  184. PRIV_PMSG * m_pLastAccessed; // Last item access in list.
  185. };
  186. // structure used to hold Ports and Buffers
  187. typedef struct PortTable
  188. {
  189. REFERENCE_TIME rtLast; // last message time packed
  190. IDirectMusicPort* pPort;
  191. IDirectMusicBuffer* pBuffer;
  192. IReferenceClock* pLatencyClock;
  193. BOOL fBufferFilled; // TRUE if there are messages in the buffer that should be sent to the port
  194. DWORD dwChannelGroups; // Number of channel groups active on the port.
  195. CLSID guidPortID; // The class id of the port, for matching with audio path requests.
  196. DMUS_PORTPARAMS8 PortParams; // PortParams returned when this port was created.
  197. DWORD dwGMFlags; // DM_PORTFLAGS_XG, DM_PORTFLAGS_GM, and DM_PORTFLAGS_GS.
  198. } PortTable;
  199. // structure to hold a channel of an accumulated parameter.
  200. // The CChannelMap keeps a linked list of these, one list each
  201. // for each parameter type.
  202. class CMergeParam : public AListItem
  203. {
  204. public:
  205. CMergeParam* GetNext() { return (CMergeParam*)AListItem::GetNext();}
  206. long m_lData; // Current parameter data.
  207. DWORD m_dwIndex; // Which layer.
  208. };
  209. class CParamMerger : public AList
  210. {
  211. public:
  212. CParamMerger();
  213. void Clear(long lInitValue);
  214. BYTE MergeMidiVolume(DWORD dwIndex, BYTE bMIDIVolume);
  215. BYTE GetVolumeStart(DWORD dwIndex);
  216. short MergeTranspose(DWORD dwIndex, short nTranspose);
  217. long MergeValue(DWORD dwIndex, long lData, long lCenter, long lRange);
  218. long GetIndexedValue(DWORD dwIndex);
  219. private:
  220. long MergeData(DWORD dwIndex, long lData);
  221. void AddHead(CMergeParam* pMergeParam) { AList::AddHead((AListItem*)pMergeParam);}
  222. CMergeParam* GetHead(){return (CMergeParam*)AList::GetHead();}
  223. CMergeParam* RemoveHead() {return (CMergeParam *) AList::RemoveHead();}
  224. void Remove(CMergeParam* pMergeParam){AList::Remove((AListItem*)pMergeParam);}
  225. void AddTail(CMergeParam* pMergeParam){AList::AddTail((AListItem*)pMergeParam);}
  226. BYTE VolumeToMidi(long lVolume);
  227. static long m_lMIDIToDB[128]; // Array for converting MIDI to centibel volume.
  228. static long m_lDBToMIDI[97]; // For converting volume to MIDI.
  229. long m_lMergeTotal; // Total for all parameters in the list, but not including m_lData.
  230. long m_lZeroIndexData; // Default (no index) data.
  231. };
  232. // structure to hold a single ChannelMap
  233. class CChannelMap
  234. {
  235. public:
  236. void Clear(); // Completely clears and resets structure.
  237. void Reset(BOOL fVolumeAndPanToo); // Clears just the midi controllers.
  238. CParamMerger m_VolumeMerger; // Set of volumes to merge.
  239. CParamMerger m_ExpressionMerger; // Set of expression controllers to merge.
  240. CParamMerger m_TransposeMerger; // Set of transpositions to merge.
  241. CParamMerger m_PitchbendMerger; // Set of pitchbends to merge.
  242. CParamMerger m_PanMerger; // Set of pans to merge.
  243. CParamMerger m_FilterMerger; // Set of filters to merge.
  244. CParamMerger m_ModWheelMerger; // Set of mod wheel controls to merge.
  245. CParamMerger m_ReverbMerger; // Set of reverb levels to merge.
  246. CParamMerger m_ChorusMerger; // Set of chorus levels to merge.
  247. DWORD dwPortIndex; // index into the PortTable
  248. DWORD dwGroup; // group number of the port
  249. DWORD dwMChannel; // channel number in the group
  250. short nTranspose; // amount to transpose
  251. WORD wFlags; // CMAP_X flags
  252. } ;
  253. #define CMAP_FREE (WORD) 1 // This channel is currently not in use.
  254. #define CMAP_STATIC (WORD) 2 // This channel is in use as a regular, static pchannel.
  255. #define CMAP_VIRTUAL (WORD) 4 // This channel is in use for a dynamic, virtual pchannel.
  256. // structure used to hold a PChannelMap block of 16.
  257. #define PCHANNEL_BLOCKSIZE 16
  258. class CChannelBlock : public AListItem
  259. {
  260. public:
  261. CChannelBlock* GetNext() { return (CChannelBlock*)AListItem::GetNext();}
  262. void Init(DWORD dwPChannelStart, DWORD dwPortIndex, DWORD dwGroup, WORD wFlags);
  263. DWORD m_dwPChannelStart; // first PChannel index
  264. CChannelMap m_aChannelMap[PCHANNEL_BLOCKSIZE];
  265. DWORD m_dwFreeChannels; // Number of channels currently free.
  266. DWORD m_dwPortIndex; // Port id, if this is completely assigned to one port.
  267. };
  268. class CChannelBlockList : public AList
  269. {
  270. public:
  271. void Clear();
  272. void AddHead(CChannelBlock* pChannelBlock) { AList::AddHead((AListItem*)pChannelBlock);}
  273. CChannelBlock* GetHead(){return (CChannelBlock*)AList::GetHead();}
  274. CChannelBlock* RemoveHead() {return (CChannelBlock *) AList::RemoveHead();}
  275. void Remove(CChannelBlock* pChannelBlock){AList::Remove((AListItem*)pChannelBlock);}
  276. void AddTail(CChannelBlock* pChannelBlock){AList::AddTail((AListItem*)pChannelBlock);}
  277. };
  278. // structure to hold a global GUID and its data
  279. typedef struct GlobalData
  280. {
  281. ~GlobalData()
  282. {
  283. if( pData )
  284. {
  285. delete [] pData;
  286. }
  287. }
  288. struct GlobalData* pNext;
  289. GUID guidType;
  290. void* pData;
  291. DWORD dwSize;
  292. } GlobalData;
  293. // structure to hold internal tempo message with relative tempo
  294. typedef struct DMInternalTempo
  295. {
  296. /* begin PRIV_PART */
  297. PRIV_PART
  298. /* end PRIV_PART */
  299. DMUS_TEMPO_PMSG tempoPMsg;
  300. float fltRelTempo; // the current relative tempo, from .5 to 2
  301. } DMInternalTempo;
  302. /* Integer constants for defining each segstate queue */
  303. #define SQ_PRI_WAIT 0
  304. #define SQ_CON_WAIT 1
  305. #define SQ_SEC_WAIT 2
  306. #define SQ_PRI_PLAY 3
  307. #define SQ_CON_PLAY 4
  308. #define SQ_SEC_PLAY 5
  309. #define SQ_PRI_DONE 6
  310. #define SQ_CON_DONE 7
  311. #define SQ_SEC_DONE 8
  312. #define SQ_COUNT 9
  313. #define IsPriQueue( dwCount ) ((dwCount % 3) == 0)
  314. #define IsConQueue( dwCount ) ((dwCount % 3) == 1)
  315. #define IsSecQueue( dwCount ) ((dwCount % 3) == 2)
  316. #define IsWaitQueue( dwCount ) (dwCount <= SQ_SEC_WAIT)
  317. #define IsPlayQueue( dwCount ) ((dwCount >= SQ_PRI_PLAY) && (dwCount <= SQ_SEC_PLAY))
  318. #define IsDoneQueue( dwCount ) (dwCount >= SQ_PRI_DONE)
  319. DEFINE_GUID(IID_CPerformance, 0xade66ea2, 0xe1c5, 0x4552, 0x85, 0x27, 0x1e, 0xef, 0xa5, 0xa, 0xfd, 0x7b);
  320. class CSong;
  321. // class CPerformance
  322. class CPerformance :
  323. public IDirectMusicPerformance8,
  324. public IDirectMusicTool,
  325. public IDirectMusicGraph,
  326. public IDirectMusicPerformanceStats,
  327. public IDirectMusicPerformanceP,
  328. public IDirectMusicSetParamHook
  329. {
  330. friend class CAudioPath;
  331. friend class CSegState;
  332. friend class CBufferManager;
  333. public:
  334. CPerformance();
  335. ~CPerformance();
  336. public:
  337. // IUnknown
  338. STDMETHODIMP QueryInterface(const IID &iid, void **ppv);
  339. STDMETHODIMP_(ULONG) AddRef();
  340. STDMETHODIMP_(ULONG) Release();
  341. // IDirectMusicPerformance
  342. STDMETHODIMP Init(IDirectMusic** ppDirectMusic,LPDIRECTSOUND pDSound,HWND hWnd );
  343. STDMETHODIMP PlaySegment(IDirectMusicSegment *pSegment,DWORD dwFlags,
  344. __int64 i64StartTime,IDirectMusicSegmentState **ppSegmentState);
  345. STDMETHODIMP Stop(IDirectMusicSegment *pSegment,
  346. IDirectMusicSegmentState *pSegmentState,MUSIC_TIME mtTime,DWORD dwFlags);
  347. STDMETHODIMP GetSegmentState(IDirectMusicSegmentState **ppSegmentState,MUSIC_TIME mtTime);
  348. STDMETHODIMP SetPrepareTime(DWORD dwMilliSeconds);
  349. STDMETHODIMP GetPrepareTime(DWORD* pdwMilliSeconds);
  350. STDMETHODIMP SetBumperLength(DWORD dwMilliSeconds);
  351. STDMETHODIMP GetBumperLength(DWORD* pdwMilliSeconds);
  352. STDMETHODIMP SendPMsg(DMUS_PMSG *pPMsg);
  353. STDMETHODIMP MusicToReferenceTime(MUSIC_TIME mtTime,REFERENCE_TIME *prtTime);
  354. STDMETHODIMP ReferenceToMusicTime(REFERENCE_TIME rtTime,MUSIC_TIME *pmtTime);
  355. STDMETHODIMP IsPlaying(IDirectMusicSegment *pSegment,IDirectMusicSegmentState *pSegState);
  356. STDMETHODIMP GetTime(REFERENCE_TIME *prtNow,MUSIC_TIME *pmtNow);
  357. STDMETHODIMP AllocPMsg(ULONG cb,DMUS_PMSG** ppPMsg);
  358. STDMETHODIMP FreePMsg(DMUS_PMSG* pPMsg);
  359. STDMETHODIMP SetNotificationHandle(HANDLE hNotificationEvent,REFERENCE_TIME rtMinimum);
  360. STDMETHODIMP GetNotificationPMsg(DMUS_NOTIFICATION_PMSG** ppNotificationPMsg);
  361. STDMETHODIMP AddNotificationType(REFGUID rguidNotification);
  362. STDMETHODIMP RemoveNotificationType(REFGUID rguidNotification);
  363. STDMETHODIMP GetGraph(IDirectMusicGraph** ppGraph);
  364. STDMETHODIMP SetGraph(IDirectMusicGraph* pGraph);
  365. STDMETHODIMP AddPort(IDirectMusicPort* pPort);
  366. STDMETHODIMP RemovePort(IDirectMusicPort* pPort);
  367. STDMETHODIMP AssignPChannelBlock(DWORD dwBlockNum,IDirectMusicPort* pPort,DWORD dwGroup);
  368. STDMETHODIMP AssignPChannel(DWORD dwPChannel,IDirectMusicPort* pPort,DWORD dwGroup,DWORD dwMChannel);
  369. STDMETHODIMP PChannelInfo(DWORD dwPChannel,IDirectMusicPort** ppPort,DWORD* pdwGroup,DWORD* pdwMChannel);
  370. STDMETHODIMP DownloadInstrument(IDirectMusicInstrument* pInst,DWORD dwPChannel,
  371. IDirectMusicDownloadedInstrument**,DMUS_NOTERANGE* pNoteRanges,
  372. DWORD dwNumNoteRanges,IDirectMusicPort**,DWORD*,DWORD*);
  373. STDMETHODIMP Invalidate(MUSIC_TIME mtTime,DWORD dwFlags);
  374. STDMETHODIMP GetParam(REFGUID rguidDataType,DWORD dwGroupBits,DWORD dwIndex,
  375. MUSIC_TIME mtTime,MUSIC_TIME* pmtNext,void* pData);
  376. STDMETHODIMP SetParam(REFGUID rguidDataType,DWORD dwGroupBits,DWORD dwIndex,
  377. MUSIC_TIME mtTime,void* pData);
  378. STDMETHODIMP GetGlobalParam(REFGUID rguidType,void* pData,DWORD dwSize);
  379. STDMETHODIMP SetGlobalParam(REFGUID rguidType,void* pData,DWORD dwSize);
  380. STDMETHODIMP GetLatencyTime(REFERENCE_TIME* prtTime);
  381. STDMETHODIMP GetQueueTime(REFERENCE_TIME* prtTime);
  382. STDMETHODIMP AdjustTime(REFERENCE_TIME rtAmount);
  383. STDMETHODIMP CloseDown(void);
  384. STDMETHODIMP GetResolvedTime(REFERENCE_TIME rtTime,REFERENCE_TIME* prtResolved,DWORD dwFlags);
  385. STDMETHODIMP MIDIToMusic(BYTE bMIDIValue,DMUS_CHORD_KEY* pChord,
  386. BYTE bPlayMode,BYTE bChordLevel,WORD *pwMusicValue);
  387. STDMETHODIMP MusicToMIDI(WORD wMusicValue,DMUS_CHORD_KEY* pChord,
  388. BYTE bPlayMode,BYTE bChordLevel,BYTE *pbMIDIValue);
  389. STDMETHODIMP TimeToRhythm(MUSIC_TIME mtTime,DMUS_TIMESIGNATURE *pTimeSig,
  390. WORD *pwMeasure,BYTE *pbBeat,BYTE *pbGrid,short *pnOffset);
  391. STDMETHODIMP RhythmToTime(WORD wMeasure,BYTE bBeat,BYTE bGrid,
  392. short nOffset,DMUS_TIMESIGNATURE *pTimeSig,MUSIC_TIME *pmtTime);
  393. // IDirectMusicPerformance8
  394. STDMETHODIMP InitAudio(IDirectMusic** ppDirectMusic,
  395. IDirectSound** ppDirectSound,
  396. HWND hWnd,
  397. DWORD dwDefaultPathType,
  398. DWORD dwPChannelCount,
  399. DWORD dwFlags,
  400. DMUS_AUDIOPARAMS *pParams);
  401. STDMETHODIMP PlaySegmentEx(IUnknown* pSource,
  402. WCHAR *pwzSegmentName,
  403. IUnknown* pTransition,
  404. DWORD dwFlags,
  405. __int64 i64StartTime,
  406. IDirectMusicSegmentState** ppSegmentState,
  407. IUnknown *pFrom,
  408. IUnknown *pAudioPath);
  409. STDMETHODIMP StopEx(IUnknown *pObjectToStop,__int64 i64StopTime,DWORD dwFlags) ;
  410. STDMETHODIMP ClonePMsg(DMUS_PMSG* pSourcePMSG,DMUS_PMSG** ppCopyPMSG) ;
  411. STDMETHODIMP CreateAudioPath( IUnknown *pSourceConfig, BOOL fActivate,
  412. IDirectMusicAudioPath **ppNewPath);
  413. STDMETHODIMP CreateStandardAudioPath(DWORD dwType, DWORD dwPChannelCount, BOOL fActivate,
  414. IDirectMusicAudioPath **ppNewPath);
  415. STDMETHODIMP SetDefaultAudioPath(IDirectMusicAudioPath *pAudioPath) ;
  416. STDMETHODIMP GetDefaultAudioPath(IDirectMusicAudioPath **pAudioPath) ;
  417. STDMETHODIMP GetParamEx(REFGUID rguidType,
  418. DWORD dwTrackID,
  419. DWORD dwGroupBits,
  420. DWORD dwIndex,
  421. MUSIC_TIME mtTime,
  422. MUSIC_TIME* pmtNext,
  423. void* pParam);
  424. // IDirectMusicTool
  425. STDMETHODIMP Init(IDirectMusicGraph* pGraph);
  426. STDMETHODIMP ProcessPMsg(IDirectMusicPerformance* pPerf,DMUS_PMSG* pPMsg);
  427. STDMETHODIMP Flush(IDirectMusicPerformance* pPerf,DMUS_PMSG* pPMsg,REFERENCE_TIME mtTime);
  428. STDMETHODIMP GetMsgDeliveryType(DWORD*);
  429. STDMETHODIMP GetMediaTypeArraySize(DWORD*);
  430. STDMETHODIMP GetMediaTypes(DWORD**,DWORD);
  431. // IDirectMusicGraph
  432. STDMETHODIMP Shutdown();
  433. STDMETHODIMP InsertTool(IDirectMusicTool *pTool,DWORD *pdwPChannels,DWORD cPChannels,LONG lIndex);
  434. STDMETHODIMP GetTool(DWORD,IDirectMusicTool**);
  435. STDMETHODIMP RemoveTool(IDirectMusicTool*);
  436. STDMETHODIMP StampPMsg( DMUS_PMSG* pPMsg );
  437. // IDirectMusicPerformanceStats
  438. STDMETHODIMP TraceAllSegments() ;
  439. STDMETHODIMP CreateSegstateList(DMUS_SEGSTATEDATA ** ppList) ;
  440. STDMETHODIMP FreeSegstateList(DMUS_SEGSTATEDATA * pList) ;
  441. // IDirectMusicPerformanceP
  442. STDMETHODIMP GetPortAndFlags(DWORD dwPChannel,IDirectMusicPort **ppPort,DWORD * pdwFlags);
  443. // IDirectMusicSetParamHook
  444. STDMETHODIMP SetParamHook(IDirectMusicParamHook *pIHook);
  445. // Access from segstate, audiopath and segment...
  446. HRESULT GetGraphInternal(IDirectMusicGraph** ppGraph);
  447. HRESULT FlushVirtualTrack(DWORD dwId,MUSIC_TIME mtTime, BOOL fLeaveNotesOn);
  448. HRESULT GetControlSegTime(MUSIC_TIME mtTime,MUSIC_TIME* pmtNextSeg);
  449. HRESULT GetPriSegTime(MUSIC_TIME mtTime,MUSIC_TIME* pmtNextSeg);
  450. HRESULT GetPathPort(CPortConfig *pConfig);
  451. void RemoveUnusedPorts();
  452. DWORD GetPortID(IDirectMusicPort * pPort);
  453. HRESULT AddPort(IDirectMusicPort* pPort,GUID *pguidPortID,
  454. DMUS_PORTPARAMS8 *pParams,DWORD *pdwPortID);
  455. private:
  456. // private member functions
  457. void Init();
  458. friend DWORD WINAPI _Transport(LPVOID);
  459. friend DWORD WINAPI _Realtime(LPVOID);
  460. HRESULT CreateThreads();
  461. HRESULT AllocPMsg(ULONG cb,PRIV_PMSG** ppPMsg);
  462. HRESULT FreePMsg(PRIV_PMSG* pPMsg);
  463. inline bool SendShortMsg(IDirectMusicBuffer* pBuffer,
  464. IDirectMusicPort* pPort,DWORD dwMsg,
  465. REFERENCE_TIME rt, DWORD dwGroup);
  466. HRESULT PackNote(DMUS_PMSG* pPMsg,REFERENCE_TIME rt );
  467. HRESULT PackCurve(DMUS_PMSG* pPMsg,REFERENCE_TIME rt );
  468. HRESULT PackMidi(DMUS_PMSG* pPMsg,REFERENCE_TIME rt );
  469. HRESULT PackSysEx(DMUS_PMSG* pPMsg,REFERENCE_TIME rt );
  470. HRESULT PackPatch(DMUS_PMSG* pPMsg,REFERENCE_TIME rt );
  471. HRESULT PackWave(DMUS_PMSG* pPMsg,REFERENCE_TIME rt );
  472. void SendBuffers();
  473. void Realtime();
  474. void Transport();
  475. void ProcessEarlyPMsgs();
  476. PRIV_PMSG *GetNextPMsg();
  477. REFERENCE_TIME GetTime();
  478. REFERENCE_TIME GetLatency();
  479. REFERENCE_TIME GetBestSegLatency( CSegState* pSeg );
  480. void PrepSegToPlay(CSegState *pSegState, bool fQueue = false);
  481. void ManageControllingTracks();
  482. void PerformSegStNode(DWORD dwList,CSegState* pSegStNode);
  483. void AddEventToTempoMap( PRIV_PMSG* pPMsg );
  484. void FlushMainEventQueues( DWORD, MUSIC_TIME mtFlush, MUSIC_TIME mtFlushUnresolved, BOOL fLeaveNotesOn); // flush all events in all queues.
  485. void FlushEventQueue( DWORD dwId,CPMsgQueue *pQueue, REFERENCE_TIME rtFlush, REFERENCE_TIME rtFlushUnresolved, BOOL fLeaveNotesOn );
  486. void ClearMusicStoppedNotification();
  487. HRESULT PlayOneSegment(
  488. CSegment* pSegment,
  489. DWORD dwFlags,
  490. __int64 i64StartTime,
  491. CSegState **ppSegState,
  492. CAudioPath *pAudioPath);
  493. HRESULT PlaySegmentInternal( CSegment* pSegment,
  494. CSong * pSong,
  495. WCHAR *pwzSegmentName,
  496. CSegment* pTransition,
  497. DWORD dwFlags,
  498. __int64 i64StartTime,
  499. IDirectMusicSegmentState** ppSegmentState,
  500. IUnknown *pFrom,
  501. CAudioPath *pAudioPath);
  502. CSegState *GetSegmentForTransition(DWORD dwFlags,MUSIC_TIME mtTime, IUnknown *pFrom);
  503. void QueuePrimarySegment( CSegState* pSeg );
  504. void QueueSecondarySegment( CSegState* pSeg );
  505. void CalculateSegmentStartTime( CSegState* pSeg );
  506. MUSIC_TIME ResolveTime( MUSIC_TIME mtTime, DWORD dwResolution, MUSIC_TIME *pmtIntervalSize );
  507. void GetTimeSig( MUSIC_TIME mtTime, DMUS_TIMESIG_PMSG* pTimeSig );
  508. void SyncTimeSig( CSegState *pSegState );
  509. void DequeueAllSegments();
  510. void AddToTempoMap( double dblTempo, MUSIC_TIME mtTime, REFERENCE_TIME rtTime );
  511. void UpdateTempoMap(MUSIC_TIME mtStart, bool fFirst, CSegState *pSegState, bool fAllDeltas = true);
  512. void IncrementTempoMap();
  513. void RecalcTempoMap(CSegState *pSegState, MUSIC_TIME mtOffset, bool fAllDeltas = true);
  514. void RevalidateRefTimes( CPMsgQueue * pList, MUSIC_TIME mtTime );
  515. void AddNotificationTypeToAllSegments( REFGUID rguidNotification );
  516. void RemoveNotificationTypeFromAllSegments( REFGUID rguidNotification );
  517. CNotificationItem* FindNotification( REFGUID rguidNotification );
  518. HRESULT GetPort(DWORD dwPortID, IDirectMusicPort **ppPort);
  519. HRESULT AllocVChannelBlock(DWORD dwPortID,DWORD dwGroup);
  520. HRESULT AllocVChannel(DWORD dwPortID, DWORD dwDrumFlags, DWORD *pdwPChannel, DWORD *pdwGroup,DWORD *pdwMChannel);
  521. HRESULT ReleasePChannel(DWORD dwPChannel);
  522. CChannelMap * GetPChannelMap( DWORD dwPChannel );
  523. HRESULT AssignPChannelBlock(DWORD dwBlockNum,DWORD dwPortIndex,DWORD dwGroup,WORD wFlags);
  524. HRESULT AssignPChannel(DWORD dwPChannel,DWORD dwPortIndex,DWORD dwGroup,DWORD dwMChannel,WORD wFlags);
  525. HRESULT PChannelIndex( DWORD dwPChannel, DWORD* pdwIndex,
  526. DWORD* pdwGroup, DWORD* pdwMChannel, short* pnTranspose = NULL );
  527. void GenerateNotification( DWORD dwNotification, MUSIC_TIME mtTime, IDirectMusicSegmentState* pSegSt );
  528. CSegState* GetPrimarySegmentAtTime( MUSIC_TIME mtTime );
  529. void ResetAllControllers( REFERENCE_TIME rtTime);
  530. void ResetAllControllers(CChannelMap* pChannelMap, REFERENCE_TIME rtTime, bool fGMReset);
  531. void DoStop( CSegState* pSegState, MUSIC_TIME mtTime, BOOL fInvalidate );
  532. void DoStop( CSegment* pSeg, MUSIC_TIME mtTime, BOOL fInvalidate );
  533. HRESULT GetChordNotificationStatus(
  534. DMUS_NOTE_PMSG* pNote,
  535. DWORD dwTrackGroup,
  536. REFERENCE_TIME rtTime,
  537. DMUS_PMSG** ppNew);
  538. void OnChordUpdateEventQueues( DMUS_NOTIFICATION_PMSG* pNotify);
  539. void OnChordUpdateEventQueue( DMUS_NOTIFICATION_PMSG* pNotify, CPMsgQueue *pQueue, REFERENCE_TIME rtFlush );
  540. #ifdef DBG
  541. void TraceAllChannelMaps();
  542. #endif
  543. // private member variables
  544. IDirectMusic8* m_pDirectMusic;
  545. IDirectSound8* m_pDirectSound;
  546. IReferenceClock* m_pClock;
  547. IDirectMusicGraph* m_pGraph;
  548. CAudioPath * m_pDefaultAudioPath; // Default audio path.
  549. DWORD m_dwNumPorts; // the number of ports
  550. PortTable* m_pPortTable; // array of ports, number equals m_dwNumPorts
  551. CChannelBlockList m_ChannelBlockList; // List of pchannel maps, in blocks of 16
  552. CChannelBlockList m_FreeChannelBlockList; // List of pchannel maps that are no longer in use
  553. CSegStateList m_SegStateQueues[SQ_COUNT]; // Lists of all active segment states.
  554. CSegStateList m_ShutDownQueue; // List of segments that are pending shutdown.
  555. CAudioPathList m_AudioPathList; // List of all active audio paths in this performance.
  556. CBufferManager m_BufferManager; // List of all buffers currently in use.
  557. DMUS_AUDIOPARAMS m_AudioParams; // Initial requirements, as set in InitAudio, by app.
  558. HANDLE m_hNotification; // notification handle set in SetNotificationHandle
  559. REFERENCE_TIME m_rtNotificationDiscard; // minimum time to hold onto a notification message
  560. CNotificationList m_NotificationList;
  561. GlobalData* m_pGlobalData; // list of global data structs
  562. DWORD m_dwAudioPathMode; // 0 for not yet set, 1 for old methods, 2 for using AudioPaths.
  563. BOOL m_fInTransportThread; // This is used to signal that the transport thread
  564. // is active and the realtime thread should hold
  565. // off on processing the early queue.
  566. BOOL m_fInTrackPlay; // This is used to signal that a track is in the process of
  567. // generating events. These will have the PRIV_FLAG_TRACK flag set.
  568. CPMsgQueue m_EarlyQueue; // List of PMsgs that play immediately.
  569. CPMsgQueue m_NearTimeQueue; // List of PMsgs that play a little early.
  570. CPMsgQueue m_OnTimeQueue; // List of PMsgs that play exactly when due.
  571. CPMsgQueue m_TempoMap; // List of tempo changes.
  572. CPMsgQueue m_OldTempoMap; // List of old tempo changes.
  573. CPMsgQueue m_NotificationQueue; // List of notification messages.
  574. CPMsgQueue m_TimeSigQueue; // List of time signature changes.
  575. // cache of allocated pmsg's
  576. #define PERF_PMSG_CB_MIN 48
  577. #define PERF_PMSG_CB_MAX 101
  578. PRIV_PMSG* m_apPMsgCache[ PERF_PMSG_CB_MAX - PERF_PMSG_CB_MIN ];
  579. DWORD m_dwInitCS;
  580. CRITICAL_SECTION m_PMsgCacheCrSec;
  581. CRITICAL_SECTION m_SegmentCrSec;
  582. CRITICAL_SECTION m_PipelineCrSec; // For all the CPMsgQueues
  583. CRITICAL_SECTION m_PChannelInfoCrSec;
  584. CRITICAL_SECTION m_GlobalDataCrSec;
  585. CRITICAL_SECTION m_RealtimeCrSec;
  586. CRITICAL_SECTION m_MainCrSec;
  587. HANDLE m_hTransport; // to wake up the Transport thread when needed
  588. HANDLE m_hRealtime;
  589. HANDLE m_hTransportThread; // to kill the Transport thread if needed
  590. HANDLE m_hRealtimeThread;
  591. REFERENCE_TIME m_rtStart; // time when this performance started
  592. REFERENCE_TIME m_rtAdjust; // adjustment time to compensate for e.g. smpte drift
  593. REFERENCE_TIME m_rtHighestPackedNoteOn; // highest time of packed note on
  594. REFERENCE_TIME m_rtEarliestStartTime; // Time of last Stop(0,0,0). New segment can not start before this.
  595. REFERENCE_TIME m_rtQueuePosition; // the highest time a message has been packed, or the latency + m_rtBumperLength, whichever is greater
  596. REFERENCE_TIME m_rtNextWakeUp; // Next time the pipeline thread needs to wake up to deliver a message.
  597. REFERENCE_TIME m_rtBumperLength; // Distance ahead of latency clock to send events down to synth.
  598. MUSIC_TIME m_mtTransported; // the highest time transported
  599. MUSIC_TIME m_mtPlayTo; // the time to play to on the next transport cycle
  600. MUSIC_TIME m_mtTempoCursor; // Tempo map has been generated up to this point.
  601. DWORD m_dwPrepareTime; // time ahead, in milliseconds, to transport
  602. DWORD m_dwBumperLength; // Millisecond version of m_rtBumperLength.
  603. long m_lMasterVolume; // master volume.
  604. float m_fltRelTempo; // relative tempo, can be from 0 to 200
  605. long m_cRef;
  606. WORD m_wRollOverCount; // tracks when timeGetTime rolls over
  607. DWORD m_dwTransportThreadID; // transport thread id
  608. DWORD m_dwRealtimeThreadID;
  609. BOOL m_fKillThread; // signal to transport thread to die
  610. BOOL m_fKillRealtimeThread;
  611. BOOL m_fPlaying;
  612. BOOL m_fMusicStopped;
  613. BOOL m_fTempoChanged; // When a tempo change occurs, refresh transport so clock time tracks don't get clobbered.
  614. IUnknown * m_pUnkDispatch; // holds the controlling unknown of the scripting object that implements IDispatch
  615. DWORD m_dwVersion; // Version number, indicating DX6, DX7, or DX8. Determined by which interface requested.
  616. IDirectMusicSegmentState * m_pGetParamSegmentState; // Set prior to playing a segment, so GetParam() can know which segment called it.
  617. DWORD m_dwGetParamFlags; // Set prior to playing a segment track, so GetParam() can know how to search for the parameter.
  618. IDirectMusicParamHook * m_pParamHook;
  619. bool m_fReleasedInTransport; // The performance had its final release in the transport thread
  620. bool m_fReleasedInRealtime; // The performance had its final release in the realtime thread
  621. };
  622. #endif // _DMPERF_H_