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.

246 lines
9.5 KiB

  1. // Copyright (c) 1999 Microsoft Corporation. All rights reserved.
  2. //
  3. // Base classes that implement aspects of a standard DirectMusic track.
  4. // Unless you're doing something pretty unusual, you should be able to inherit from one
  5. // of these classes and reduce the work needed to implement a new track type.
  6. //
  7. // * CBasicTrack
  8. // Contains stubs that no-op or return notimpl most track methods.
  9. // You implement Load, InitPlay, EndPlay, PlayMusicOrClock, and Clone.
  10. //
  11. // * CPlayingTrack
  12. // CBasicTrack plus standard implementations of InitPlay, EndPlay, Clone.
  13. // PlayMusicOrClock and Load are partially implemented. You fill in the rest by implementing
  14. // the methods PlayItem and LoadRiff.
  15. // You also must implement classes for event items and (optionally) state data.
  16. #pragma once
  17. #include "dmusici.h"
  18. #include "validate.h"
  19. #include "miscutil.h"
  20. #include "tlist.h"
  21. #include "smartref.h"
  22. const int gc_RefPerMil = 10000; // Value for converting from reference time to milliseconds
  23. //////////////////////////////////////////////////////////////////////
  24. // TrackHelpCreateInstance
  25. // Standard implementation of CreateInstance to call from class factory templated on
  26. // the type of your derived class. Your class constructor must take an HRESULT pointer
  27. // it can use to return an error.
  28. template <class T>
  29. HRESULT TrackHelpCreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv, T *pUnused = NULL)
  30. {
  31. // ��
  32. // pUnused is just a dummy to force generation of the correct template type T.
  33. // Compiler bug?
  34. *ppv = NULL;
  35. if (pUnknownOuter)
  36. return CLASS_E_NOAGGREGATION;
  37. HRESULT hr = S_OK;
  38. T *pInst = new T(&hr);
  39. if (pInst == NULL)
  40. return E_OUTOFMEMORY;
  41. if (FAILED(hr))
  42. return hr;
  43. return pInst->QueryInterface(iid, ppv);
  44. }
  45. //////////////////////////////////////////////////////////////////////
  46. // CBasicTrack
  47. //
  48. // Base class with a standard implementation the following aspects of a DirectMusic track:
  49. // - IUnknown: AddRef, Release, and QueryInterface (QI for IUnknown, IDirectMusicTrack, IDirectMusicTrack8, IPersistStream, IPersist)
  50. // - IPersistStrea: stubs out GetClassID, IsDirty, Save, and GetSizeMax.
  51. // - IDirectMusicTrack:
  52. // stubs out IsParamSupported, Init, GetParam, SetParam, AddNotificationType, RemoveNotificationType.
  53. // implements millisecond time conversion for PlayEx, GetParamEx, SetParamEx.
  54. // - Declares and initializes a critical section.
  55. //
  56. // Pure virtual functions you must implement:
  57. // - Load
  58. // - InitPlay
  59. // - EndPlay
  60. // - Clone
  61. // - PlayMusicOrClock (single method called by both Play and PlayEx)
  62. class CBasicTrack
  63. : public IPersistStream,
  64. public IDirectMusicTrack8
  65. {
  66. public:
  67. // IUnknown
  68. STDMETHOD(QueryInterface)(const IID &iid, void **ppv);
  69. STDMETHOD_(ULONG, AddRef)();
  70. STDMETHOD_(ULONG, Release)();
  71. // IPersistStream functions
  72. STDMETHOD(GetClassID)(CLSID* pClassID);
  73. STDMETHOD(IsDirty)() {return S_FALSE;}
  74. STDMETHOD(Load)(IStream* pStream) = 0;
  75. STDMETHOD(Save)(IStream* pStream, BOOL fClearDirty) {return E_NOTIMPL;}
  76. STDMETHOD(GetSizeMax)(ULARGE_INTEGER* pcbSize) {return E_NOTIMPL;}
  77. // IDirectMusicTrack methods
  78. STDMETHOD(IsParamSupported)(REFGUID rguid) {return DMUS_E_TYPE_UNSUPPORTED;}
  79. STDMETHOD(Init)(IDirectMusicSegment *pSegment);
  80. STDMETHOD(InitPlay)(
  81. IDirectMusicSegmentState *pSegmentState,
  82. IDirectMusicPerformance *pPerformance,
  83. void **ppStateData,
  84. DWORD dwTrackID,
  85. DWORD dwFlags) = 0;
  86. STDMETHOD(EndPlay)(void *pStateData) = 0;
  87. STDMETHOD(Play)(
  88. void *pStateData,
  89. MUSIC_TIME mtStart,
  90. MUSIC_TIME mtEnd,
  91. MUSIC_TIME mtOffset,
  92. DWORD dwFlags,
  93. IDirectMusicPerformance* pPerf,
  94. IDirectMusicSegmentState* pSegSt,
  95. DWORD dwVirtualID);
  96. STDMETHOD(GetParam)(REFGUID rguid,MUSIC_TIME mtTime,MUSIC_TIME* pmtNext,void *pData) {return DMUS_E_GET_UNSUPPORTED;}
  97. STDMETHOD(SetParam)(REFGUID rguid,MUSIC_TIME mtTime,void *pData) {return DMUS_E_SET_UNSUPPORTED;}
  98. STDMETHOD(AddNotificationType)(REFGUID rguidNotification) {return E_NOTIMPL;}
  99. STDMETHOD(RemoveNotificationType)(REFGUID rguidNotification) {return E_NOTIMPL;}
  100. STDMETHOD(Clone)(MUSIC_TIME mtStart,MUSIC_TIME mtEnd,IDirectMusicTrack** ppTrack) = 0;
  101. // IDirectMusicTrack8
  102. STDMETHODIMP PlayEx(
  103. void* pStateData,
  104. REFERENCE_TIME rtStart,
  105. REFERENCE_TIME rtEnd,
  106. REFERENCE_TIME rtOffset,
  107. DWORD dwFlags,
  108. IDirectMusicPerformance* pPerf,
  109. IDirectMusicSegmentState* pSegSt,
  110. DWORD dwVirtualID);
  111. STDMETHODIMP GetParamEx(REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME* prtNext, void* pParam, void * pStateData, DWORD dwFlags);
  112. STDMETHODIMP SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,void* pParam, void * pStateData, DWORD dwFlags) ;
  113. STDMETHODIMP Compose(IUnknown* pContext,
  114. DWORD dwTrackGroup,
  115. IDirectMusicTrack** ppResultTrack) ;
  116. STDMETHODIMP Join(IDirectMusicTrack* pNewTrack,
  117. MUSIC_TIME mtJoin,
  118. IUnknown* pContext,
  119. DWORD dwTrackGroup,
  120. IDirectMusicTrack** ppResultTrack) ;
  121. protected:
  122. // plModuleLockCounter: a pointer to your .dll's lock counter that will be incremented/decremented when the track is created/destroyed
  123. // rclsid: the classid of your track
  124. CBasicTrack(long *plModuleLockCounter, const CLSID &rclsid); // Takes pointer to lock counter to increment and decrement on component creation/destruction. Typically, pass &g_cComponent and the clsid of your track.
  125. virtual ~CBasicTrack() { InterlockedDecrement(m_plModuleLockCounter); }
  126. // Shared implentation of play for either music or clock time.
  127. virtual HRESULT PlayMusicOrClock(
  128. void *pStateData,
  129. MUSIC_TIME mtStart,
  130. MUSIC_TIME mtEnd,
  131. MUSIC_TIME mtOffset,
  132. REFERENCE_TIME rtOffset,
  133. DWORD dwFlags,
  134. IDirectMusicPerformance* pPerf,
  135. IDirectMusicSegmentState* pSegSt,
  136. DWORD dwVirtualID,
  137. bool fClockTime) = 0;
  138. // Use this critical section to guard entry points for thread safety
  139. CRITICAL_SECTION m_CriticalSection;
  140. private:
  141. long m_cRef;
  142. long *m_plModuleLockCounter;
  143. const CLSID &m_rclsid;
  144. };
  145. //////////////////////////////////////////////////////////////////////
  146. // CPlayingTrack
  147. //
  148. // Base class that provides standard implementations of InitPlay, EndPlay, and Clone.
  149. // Also, partially implemented are:
  150. // - PlayMusicOrClock. You must implement the pure virual function PlayItem, which is
  151. // called during play as each event needs to be performed.
  152. // - Load. This just does a few standard things (clearing the event list, incrementing the
  153. // state data counter, optionally getting the loader, and sorting the results). It
  154. // depends on your implementation of the pure virtual function LoadRiff that you must
  155. // implement to do the real processing.
  156. // Template types required:
  157. // T: Your derived class (needed for New in clone). Must have a constructor that takes a pointer to an HRESULT.
  158. // StateData: Type for your state data. Must contain dwValidate, used to check if the track has been reloaded, and pCurrentEvent, a pointer to the next event item to be played.
  159. // EventItem: Type for the event items in your track. Must contain lTriggerTime, which is the time during Play when PlayItem will be called. Must implement Clone, which copies another EventItem, shifting it back according to a start MUSIC_TIME.
  160. // Standard state data for use with CPlayingTrack. Or inherit from it and add more information.
  161. template<class EventItem>
  162. struct CStandardStateData
  163. {
  164. CStandardStateData() : dwValidate(0), pCurrentEvent(NULL) {}
  165. DWORD dwValidate;
  166. TListItem<EventItem> *pCurrentEvent;
  167. };
  168. template<class T, class EventItem, class StateData = CStandardStateData<EventItem> >
  169. class CPlayingTrack
  170. : public CBasicTrack
  171. {
  172. public:
  173. typedef StateData statedata;
  174. STDMETHOD(Load)(IStream* pIStream);
  175. STDMETHOD(InitPlay)(
  176. IDirectMusicSegmentState *pSegmentState,
  177. IDirectMusicPerformance *pPerformance,
  178. void **ppStateData,
  179. DWORD dwTrackID,
  180. DWORD dwFlags);
  181. STDMETHOD(EndPlay)(void *pStateData);
  182. STDMETHOD(Clone)(MUSIC_TIME mtStart,MUSIC_TIME mtEnd,IDirectMusicTrack** ppTrack);
  183. virtual HRESULT PlayMusicOrClock(
  184. void *pStateData,
  185. MUSIC_TIME mtStart,
  186. MUSIC_TIME mtEnd,
  187. MUSIC_TIME mtOffset,
  188. REFERENCE_TIME rtOffset,
  189. DWORD dwFlags,
  190. IDirectMusicPerformance* pPerf,
  191. IDirectMusicSegmentState* pSegSt,
  192. DWORD dwVirtualID,
  193. bool fClockTime);
  194. protected:
  195. // plModuleLockCounter: a pointer to your .dll's lock counter that will be incremented/decremented when the track is created/destroyed
  196. // rclsid: the classid of your track
  197. // fNeedsLoader: pass true if you will need a reference to the loader when your LoadRiff method is called
  198. // fPlayInvalidations: if true, then your items will be played more than once when an invalidation occurs
  199. // pass false if your track doesn't want to respond to invalidations
  200. CPlayingTrack(long *plModuleLockCounter, const CLSID &rclsid, bool fNeedsLoader, bool fPlayInvalidations);
  201. virtual HRESULT PlayItem(
  202. const EventItem &item,
  203. StateData &state,
  204. IDirectMusicPerformance *pPerf,
  205. IDirectMusicSegmentState* pSegSt,
  206. DWORD dwVirtualID,
  207. MUSIC_TIME mtOffset,
  208. REFERENCE_TIME rtOffset,
  209. bool fClockTime) = 0; // feel free to add additional parameters if you need to pass more information from Play
  210. virtual HRESULT LoadRiff(SmartRef::RiffIter &ri, IDirectMusicLoader *pIDMLoader) = 0; // note that pIDMLoader will be null unless true is passed for fNeedsLoader in constructor
  211. virtual TListItem<EventItem> *Seek(MUSIC_TIME mtStart); // this method is provided in case you want to inherit and intercept when a seek is happening
  212. // Increment this counter in Load, causing the state data to synchonize with the new events
  213. DWORD m_dwValidate;
  214. TList<EventItem> m_EventList;
  215. bool m_fNeedsLoader;
  216. bool m_fPlayInvalidations;
  217. };
  218. #include "trackhelp.inl"