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.

291 lines
8.0 KiB

  1. // TimeShift.cpp : Implementation of CTimeShiftTool
  2. //
  3. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved
  4. //
  5. #include "dmusicc.h"
  6. #include "dmusici.h"
  7. #include "debug.h"
  8. #include "timeshift.h"
  9. #include "toolhelp.h"
  10. CTimeShiftTool::CTimeShiftTool()
  11. {
  12. ParamInfo Params[DMUS_TIMESHIFT_PARAMCOUNT] =
  13. {
  14. { DMUS_TIMESHIFT_TIMEUNIT, MPT_ENUM,MP_CAPS_ALL, DMUS_TIME_UNIT_MTIME,DMUS_TIME_UNIT_1,DMUS_TIME_UNIT_GRID,
  15. L"",L"Resolution Units",L"Music Clicks,Grid,Beat,Bar,64th note triplets,64th notes,32nd note triplets,32nd notes,16th note triplets,16th notes,8th note triplets,8th notes,Quarter note triplets,Quarter notes,Half note triplets,Half notes,Whole note triplets,Whole notes" },
  16. { DMUS_TIMESHIFT_RANGE, MPT_INT,MP_CAPS_ALL,0,200,0,
  17. L"Clicks",L"Shift",NULL}, // Time shift - default to 0 (no change)
  18. { DMUS_TIMESHIFT_OFFSET, MPT_INT,MP_CAPS_ALL,-200,200,0,
  19. L"Clicks",L"Random Range",NULL}, // Randmomize - default to 0 (no change)
  20. };
  21. InitParams(DMUS_TIMESHIFT_PARAMCOUNT,Params);
  22. m_fMusicTime = TRUE; // override default setting.
  23. }
  24. STDMETHODIMP_(ULONG) CTimeShiftTool::AddRef()
  25. {
  26. return InterlockedIncrement(&m_cRef);
  27. }
  28. STDMETHODIMP_(ULONG) CTimeShiftTool::Release()
  29. {
  30. if( 0 == InterlockedDecrement(&m_cRef) )
  31. {
  32. delete this;
  33. return 0;
  34. }
  35. return m_cRef;
  36. }
  37. STDMETHODIMP CTimeShiftTool::QueryInterface(const IID &iid, void **ppv)
  38. {
  39. if (iid == IID_IUnknown || iid == IID_IDirectMusicTool || iid == IID_IDirectMusicTool8)
  40. {
  41. *ppv = static_cast<IDirectMusicTool8*>(this);
  42. }
  43. else if(iid == IID_IPersistStream)
  44. {
  45. *ppv = static_cast<IPersistStream*>(this);
  46. }
  47. else if(iid == IID_IDirectMusicTimeShiftTool)
  48. {
  49. *ppv = static_cast<IDirectMusicTimeShiftTool*>(this);
  50. }
  51. else if(iid == IID_IMediaParams)
  52. {
  53. *ppv = static_cast<IMediaParams*>(this);
  54. }
  55. else if(iid == IID_IMediaParamInfo)
  56. {
  57. *ppv = static_cast<IMediaParamInfo*>(this);
  58. }
  59. else if(iid == IID_ISpecifyPropertyPages)
  60. {
  61. *ppv = static_cast<ISpecifyPropertyPages*>(this);
  62. }
  63. else
  64. {
  65. *ppv = NULL;
  66. return E_NOINTERFACE;
  67. }
  68. AddRef();
  69. return S_OK;
  70. }
  71. //////////////////////////////////////////////////////////////////////
  72. // IPersistStream
  73. STDMETHODIMP CTimeShiftTool::GetClassID(CLSID* pClassID)
  74. {
  75. if (pClassID)
  76. {
  77. *pClassID = CLSID_DirectMusicTimeShiftTool;
  78. return S_OK;
  79. }
  80. return E_POINTER;
  81. }
  82. //////////////////////////////////////////////////////////////////////
  83. // IPersistStream Methods:
  84. STDMETHODIMP CTimeShiftTool::IsDirty()
  85. {
  86. if (m_fDirty) return S_OK;
  87. else return S_FALSE;
  88. }
  89. STDMETHODIMP CTimeShiftTool::Load(IStream* pStream)
  90. {
  91. EnterCriticalSection(&m_CrSec);
  92. DWORD dwChunkID;
  93. DWORD dwSize;
  94. HRESULT hr = pStream->Read(&dwChunkID, sizeof(dwChunkID), NULL);
  95. hr = pStream->Read(&dwSize, sizeof(dwSize), NULL);
  96. if(SUCCEEDED(hr) && (dwChunkID == FOURCC_TIMESHIFT_CHUNK))
  97. {
  98. DMUS_IO_TIMESHIFT_HEADER Header;
  99. memset(&Header,0,sizeof(Header));
  100. hr = pStream->Read(&Header, min(sizeof(Header),dwSize), NULL);
  101. if (SUCCEEDED(hr))
  102. {
  103. SetParam(DMUS_TIMESHIFT_TIMEUNIT,(float) Header.dwTimeUnit);
  104. SetParam(DMUS_TIMESHIFT_RANGE,(float) Header.dwRange);
  105. SetParam(DMUS_TIMESHIFT_OFFSET,(float) Header.lOffset);
  106. }
  107. }
  108. m_fDirty = FALSE;
  109. LeaveCriticalSection(&m_CrSec);
  110. return hr;
  111. }
  112. STDMETHODIMP CTimeShiftTool::Save(IStream* pStream, BOOL fClearDirty)
  113. {
  114. EnterCriticalSection(&m_CrSec);
  115. DWORD dwChunkID = FOURCC_TIMESHIFT_CHUNK;
  116. DWORD dwSize = sizeof(DMUS_IO_TIMESHIFT_HEADER);
  117. HRESULT hr = pStream->Write(&dwChunkID, sizeof(dwChunkID), NULL);
  118. if (SUCCEEDED(hr))
  119. {
  120. hr = pStream->Write(&dwSize, sizeof(dwSize), NULL);
  121. }
  122. if (SUCCEEDED(hr))
  123. {
  124. DMUS_IO_TIMESHIFT_HEADER Header;
  125. GetParamInt(DMUS_TIMESHIFT_TIMEUNIT,MAX_REF_TIME,(long *) &Header.dwTimeUnit);
  126. GetParamInt(DMUS_TIMESHIFT_RANGE,MAX_REF_TIME,(long *)&Header.dwRange);
  127. GetParamInt(DMUS_TIMESHIFT_OFFSET,MAX_REF_TIME,&Header.lOffset);
  128. hr = pStream->Write(&Header, sizeof(Header),NULL);
  129. }
  130. if (fClearDirty) m_fDirty = FALSE;
  131. LeaveCriticalSection(&m_CrSec);
  132. return hr;
  133. }
  134. STDMETHODIMP CTimeShiftTool::GetSizeMax(ULARGE_INTEGER* pcbSize)
  135. {
  136. if (pcbSize == NULL)
  137. {
  138. return E_POINTER;
  139. }
  140. pcbSize->QuadPart = sizeof(DMUS_IO_TIMESHIFT_HEADER) + 8; // Data plus RIFF header.
  141. return S_OK;
  142. }
  143. STDMETHODIMP CTimeShiftTool::GetPages(CAUUID * pPages)
  144. {
  145. pPages->cElems = 1;
  146. pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
  147. if (pPages->pElems == NULL)
  148. return E_OUTOFMEMORY;
  149. *(pPages->pElems) = CLSID_TimeShiftPage;
  150. return NOERROR;
  151. }
  152. /////////////////////////////////////////////////////////////////
  153. // IDirectMusicTool
  154. STDMETHODIMP CTimeShiftTool::ProcessPMsg( IDirectMusicPerformance* pPerf,
  155. DMUS_PMSG* pPMsg )
  156. {
  157. // returning S_FREE frees the message. If StampPMsg()
  158. // fails, there is no destination for this message so
  159. // free it.
  160. if(NULL == pPMsg->pGraph )
  161. {
  162. return DMUS_S_FREE;
  163. }
  164. if (FAILED(pPMsg->pGraph->StampPMsg(pPMsg)))
  165. {
  166. return DMUS_S_FREE;
  167. }
  168. // Only adjust the timing of notes.
  169. if( pPMsg->dwType == DMUS_PMSGT_NOTE )
  170. {
  171. REFERENCE_TIME rtTime;
  172. if (m_fMusicTime) rtTime = pPMsg->mtTime;
  173. else rtTime = pPMsg->rtTime;
  174. DMUS_NOTE_PMSG *pNote = (DMUS_NOTE_PMSG *) pPMsg;
  175. IDirectMusicPerformance8 *pPerf8; // We'll need the DX8 interface to access ClonePMsg.
  176. if (SUCCEEDED(pPerf->QueryInterface(IID_IDirectMusicPerformance8,(void **)&pPerf8)))
  177. {
  178. long lOffset;
  179. DWORD dwRange;
  180. long lTimeUnit;
  181. GetParamInt(DMUS_TIMESHIFT_TIMEUNIT,rtTime,&lTimeUnit);
  182. GetParamInt(DMUS_TIMESHIFT_RANGE,rtTime,(long *)&dwRange);
  183. GetParamInt(DMUS_TIMESHIFT_OFFSET,rtTime,&lOffset);
  184. DMUS_TIMESIGNATURE TimeSig;
  185. if (SUCCEEDED(pPerf8->GetParamEx(GUID_TimeSignature,pNote->dwVirtualTrackID,pNote->dwGroupID,DMUS_SEG_ANYTRACK,pNote->mtTime,NULL,&TimeSig)))
  186. {
  187. long lResolution = CToolHelper::TimeUnitToTicks(lTimeUnit,&TimeSig);
  188. if (lResolution < 1) lResolution = 1;
  189. if (dwRange)
  190. {
  191. dwRange *= lResolution;
  192. pNote->mtTime += (rand() % (dwRange << 1)) - dwRange;
  193. pNote->dwFlags &= ~DMUS_PMSGF_REFTIME;
  194. }
  195. if (lOffset)
  196. {
  197. lOffset *= lResolution;
  198. pNote->mtTime += lOffset;
  199. pNote->dwFlags &= ~DMUS_PMSGF_REFTIME;
  200. }
  201. }
  202. pPerf8->Release();
  203. }
  204. }
  205. return DMUS_S_REQUEUE;
  206. }
  207. STDMETHODIMP CTimeShiftTool::Clone( IDirectMusicTool ** ppTool)
  208. {
  209. CTimeShiftTool *pNew = new CTimeShiftTool;
  210. if (pNew)
  211. {
  212. HRESULT hr = pNew->CopyParamsFromSource(this);
  213. if (SUCCEEDED(hr))
  214. {
  215. *ppTool = (IDirectMusicTool *) pNew;
  216. }
  217. else
  218. {
  219. delete pNew;
  220. }
  221. return hr;
  222. }
  223. else
  224. {
  225. return E_OUTOFMEMORY;
  226. }
  227. }
  228. STDMETHODIMP CTimeShiftTool::SetTimeUnit(DWORD dwTimeUnit)
  229. {
  230. return SetParam(DMUS_TIMESHIFT_TIMEUNIT,(float) dwTimeUnit);
  231. }
  232. STDMETHODIMP CTimeShiftTool::SetRange( DWORD dwRange)
  233. {
  234. return SetParam(DMUS_TIMESHIFT_RANGE,(float)dwRange);
  235. }
  236. STDMETHODIMP CTimeShiftTool::SetOffset( long lOffset)
  237. {
  238. return SetParam(DMUS_TIMESHIFT_OFFSET,(float)lOffset);
  239. }
  240. STDMETHODIMP CTimeShiftTool::GetTimeUnit(DWORD * pdwTimeUnit)
  241. {
  242. return GetParamInt(DMUS_TIMESHIFT_TIMEUNIT,MAX_REF_TIME,(long *) pdwTimeUnit);
  243. }
  244. STDMETHODIMP CTimeShiftTool::GetRange(DWORD *pdwRange)
  245. {
  246. return GetParamInt(DMUS_TIMESHIFT_RANGE,MAX_REF_TIME, (long *) pdwRange);
  247. }
  248. STDMETHODIMP CTimeShiftTool::GetOffset(long *plOffset)
  249. {
  250. return GetParamInt(DMUS_TIMESHIFT_OFFSET,MAX_REF_TIME, plOffset);
  251. }