Leaked source code of windows server 2003
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.

282 lines
12 KiB

  1. // Copyright (c) 1999 Microsoft Corporation. All rights reserved.
  2. //
  3. // Implementation of CAutDirectMusicSegment.
  4. //
  5. #include "stdinc.h"
  6. #include "autsegment.h"
  7. #include "activescript.h"
  8. #include "autconstants.h"
  9. #include <limits>
  10. const WCHAR CAutDirectMusicSegment::ms_wszClassName[] = L"Segment";
  11. //////////////////////////////////////////////////////////////////////
  12. // Method Names/DispIDs
  13. const DISPID DMPDISP_Load = 1;
  14. const DISPID DMPDISP_Play = 2;
  15. const DISPID DMPDISP_Stop = 3;
  16. const DISPID DMPDISP_DownloadSoundData = 4;
  17. const DISPID DMPDISP_UnloadSoundData = 5;
  18. const DISPID DMPDISP_Recompose = 6;
  19. const AutDispatchMethod CAutDirectMusicSegment::ms_Methods[] =
  20. {
  21. // dispid, name,
  22. // return: type, (opt), (iid),
  23. // parm 1: type, opt, iid,
  24. // parm 2: type, opt, iid,
  25. // ...
  26. // ADT_None
  27. { DMPDISP_Load, L"Load",
  28. ADPARAM_NORETURN,
  29. ADT_None },
  30. { DMPDISP_Play, L"Play",
  31. ADT_Interface, true, &IID_IUnknown, // returned segment state
  32. ADT_Long, true, &IID_NULL, // flags
  33. ADT_Interface, true, &IID_IDirectMusicAudioPath, // audio path
  34. ADT_Interface, true, &IID_IDirectMusicSegment, // template segment for transition
  35. ADT_Interface, true, &IID_IDirectMusicSegmentState, // playing segment to replace
  36. ADT_None },
  37. { DMPDISP_Stop, L"Stop",
  38. ADPARAM_NORETURN,
  39. ADT_Long, true, &IID_NULL, // flags
  40. ADT_None },
  41. { DMPDISP_DownloadSoundData, L"DownloadSoundData",
  42. ADPARAM_NORETURN,
  43. ADT_Interface, true, &IID_IDirectMusicAudioPath, // audio path
  44. ADT_None },
  45. { DMPDISP_UnloadSoundData, L"UnloadSoundData",
  46. ADPARAM_NORETURN,
  47. ADT_Interface, true, &IID_IDirectMusicAudioPath, // audio path
  48. ADT_None },
  49. { DMPDISP_Recompose, L"Recompose",
  50. ADPARAM_NORETURN,
  51. ADT_None },
  52. { DISPID_UNKNOWN }
  53. };
  54. const DispatchHandlerEntry<CAutDirectMusicSegment> CAutDirectMusicSegment::ms_Handlers[] =
  55. {
  56. { DMPDISP_Load, Load },
  57. { DMPDISP_Play, Play },
  58. { DMPDISP_Stop, Stop },
  59. { DMPDISP_DownloadSoundData, DownloadSoundData },
  60. { DMPDISP_UnloadSoundData, UnloadSoundData },
  61. { DMPDISP_Recompose, Recompose },
  62. { DISPID_UNKNOWN }
  63. };
  64. //////////////////////////////////////////////////////////////////////
  65. // Creation
  66. CAutDirectMusicSegment::CAutDirectMusicSegment(
  67. IUnknown* pUnknownOuter,
  68. const IID& iid,
  69. void** ppv,
  70. HRESULT *phr)
  71. : BaseImpSegment(pUnknownOuter, iid, ppv, phr)
  72. {
  73. }
  74. HRESULT CAutDirectMusicSegment::CreateInstance(
  75. IUnknown* pUnknownOuter,
  76. const IID& iid,
  77. void** ppv)
  78. {
  79. HRESULT hr = S_OK;
  80. CAutDirectMusicSegment *pInst = new CAutDirectMusicSegment(pUnknownOuter, iid, ppv, &hr);
  81. if (FAILED(hr))
  82. {
  83. delete pInst;
  84. return hr;
  85. }
  86. if (pInst == NULL)
  87. return E_OUTOFMEMORY;
  88. return hr;
  89. }
  90. //////////////////////////////////////////////////////////////////////
  91. // Private Functions
  92. HRESULT
  93. CAutDirectMusicSegment::Load(AutDispatchDecodedParams *paddp)
  94. {
  95. // Loading is actually implemented generically by container items.
  96. // If we're here, we're already loaded and don't need to do anything.
  97. return S_OK;
  98. }
  99. const FlagMapEntry gc_flagmapPlay[] =
  100. {
  101. { ScriptConstants::IsSecondary, DMUS_SEGF_SECONDARY },
  102. { ScriptConstants::IsControl, DMUS_SEGF_CONTROL | DMUS_SEGF_SECONDARY },
  103. { ScriptConstants::AtFinish, DMUS_SEGF_QUEUE },
  104. { ScriptConstants::AtGrid, DMUS_SEGF_GRID },
  105. { ScriptConstants::AtBeat, DMUS_SEGF_BEAT },
  106. { ScriptConstants::AtMeasure, DMUS_SEGF_MEASURE },
  107. { ScriptConstants::AtMarker, DMUS_SEGF_MARKER },
  108. { ScriptConstants::AtImmediate, DMUS_SEGF_DEFAULT }, // this flag gets flipped later
  109. { ScriptConstants::AlignToBar, DMUS_SEGF_ALIGN | DMUS_SEGF_MEASURE | DMUS_SEGF_VALID_START_BEAT },
  110. { ScriptConstants::AlignToBeat, DMUS_SEGF_ALIGN | DMUS_SEGF_BEAT | DMUS_SEGF_VALID_START_GRID },
  111. { ScriptConstants::AlignToSegment, DMUS_SEGF_ALIGN | DMUS_SEGF_SEGMENTEND | DMUS_SEGF_VALID_START_MEASURE },
  112. { ScriptConstants::NoCutoff, DMUS_SEGF_NOINVALIDATE },
  113. { 0 }
  114. };
  115. const FlagMapEntry gc_flagmapPlayTransCommand[] =
  116. {
  117. { ScriptConstants::PlayFill, DMUS_COMMANDT_FILL },
  118. { ScriptConstants::PlayIntro, DMUS_COMMANDT_INTRO },
  119. { ScriptConstants::PlayBreak, DMUS_COMMANDT_BREAK },
  120. { ScriptConstants::PlayEnd, DMUS_COMMANDT_END },
  121. { ScriptConstants::PlayEndAndIntro, DMUS_COMMANDT_ENDANDINTRO },
  122. { 0 }
  123. };
  124. const FlagMapEntry gc_flagmapPlayTransFlags[] =
  125. {
  126. { ScriptConstants::AtFinish, DMUS_COMPOSEF_SEGMENTEND },
  127. { ScriptConstants::AtGrid, DMUS_COMPOSEF_GRID },
  128. { ScriptConstants::AtBeat, DMUS_COMPOSEF_BEAT },
  129. { ScriptConstants::AtMeasure, DMUS_COMPOSEF_MEASURE },
  130. { ScriptConstants::AtMarker, DMUS_COMPOSEF_MARKER },
  131. { ScriptConstants::AtImmediate, DMUS_COMPOSEF_IMMEDIATE },
  132. { ScriptConstants::AlignToBar, DMUS_COMPOSEF_ALIGN | DMUS_COMPOSEF_MEASURE },
  133. { ScriptConstants::AlignToBeat, DMUS_COMPOSEF_ALIGN | DMUS_COMPOSEF_BEAT },
  134. { ScriptConstants::AlignToSegment, DMUS_COMPOSEF_ALIGN | DMUS_COMPOSEF_SEGMENTEND },
  135. { ScriptConstants::PlayModulate, DMUS_COMPOSEF_MODULATE },
  136. { 0 }
  137. };
  138. HRESULT
  139. CAutDirectMusicSegment::Play(AutDispatchDecodedParams *paddp)
  140. {
  141. IDirectMusicSegmentState **ppSegSt = reinterpret_cast<IDirectMusicSegmentState **>(paddp->pvReturn);
  142. LONG lFlags = paddp->params[0].lVal;
  143. IDirectMusicAudioPath *pAudioPath = reinterpret_cast<IDirectMusicAudioPath*>(paddp->params[1].iVal);
  144. IDirectMusicSegment *pTransitionSegment = reinterpret_cast<IDirectMusicSegment*>(paddp->params[2].iVal);
  145. IDirectMusicSegmentState *pFromSegmentState = reinterpret_cast<IDirectMusicSegmentState*>(paddp->params[3].iVal);
  146. const LONG lFlagsNonPrimary = ScriptConstants::IsSecondary | ScriptConstants::IsControl;
  147. const LONG lFlagsTransition = ScriptConstants::PlayFill | ScriptConstants::PlayIntro | ScriptConstants::PlayBreak | ScriptConstants::PlayEnd | ScriptConstants::PlayEndAndIntro;
  148. if ((lFlags & lFlagsNonPrimary) && (lFlags & lFlagsTransition))
  149. {
  150. // Transitions may only be used when playing primary segments. Return a runtime error.
  151. Trace(1, "Error: Play called with IsSecondary or IsControl flag as well as a transition flag (PlayFill, PlayIntro, etc..). Transitions can only be used with primary segments.\n");
  152. return E_INVALIDARG;
  153. }
  154. HRESULT hr = S_OK;
  155. IDirectMusicPerformance8 *pPerformance = CActiveScriptManager::GetCurrentPerformanceWEAK();
  156. if (lFlags & lFlagsTransition)
  157. {
  158. // do a transition
  159. DWORD dwCommand = MapFlags(lFlags, gc_flagmapPlayTransCommand);
  160. assert(dwCommand < std::numeric_limits<WORD>::max()); // the command parameter is a WORD. this just checks that there's nothing truncated.
  161. DWORD dwFlags = MapFlags(lFlags, gc_flagmapPlayTransFlags);
  162. // Always play the entire transition instead of doing the old (slightly strange) 1 bar / long stuff.
  163. // Also, always use an embedded audio path if one exists.
  164. dwFlags |= (DMUS_COMPOSEF_ENTIRE_TRANSITION | DMUS_COMPOSEF_USE_AUDIOPATH);
  165. IDirectMusicComposer8 *pComposer = CActiveScriptManager::GetComposerWEAK();
  166. hr = pComposer->AutoTransition(pPerformance, m_pITarget, dwCommand, dwFlags, NULL, NULL, ppSegSt, NULL);
  167. }
  168. else
  169. {
  170. DWORD dwFlags = MapFlags(lFlags, gc_flagmapPlay);
  171. // Reverse the default flag because our flag means the opposite. Default is the default and immediate is the flag.
  172. dwFlags ^= DMUS_SEGF_DEFAULT;
  173. if (pTransitionSegment)
  174. dwFlags |= DMUS_SEGF_AUTOTRANSITION;
  175. __int64 i64IntendedStartTime;
  176. DWORD dwIntendedStartTimeFlags;
  177. CActiveScriptManager::GetCurrentTimingContext(&i64IntendedStartTime, &dwIntendedStartTimeFlags);
  178. hr = pPerformance->PlaySegmentEx(m_pITarget, 0, pTransitionSegment, dwFlags | dwIntendedStartTimeFlags, i64IntendedStartTime, ppSegSt, pFromSegmentState, pAudioPath);
  179. }
  180. if (FAILED(hr))
  181. return hr;
  182. return S_OK;
  183. }
  184. const FlagMapEntry gc_flagmapStop[] =
  185. {
  186. { ScriptConstants::AtGrid, DMUS_SEGF_GRID },
  187. { ScriptConstants::AtBeat, DMUS_SEGF_BEAT },
  188. { ScriptConstants::AtMeasure, DMUS_SEGF_MEASURE },
  189. { ScriptConstants::AtMarker, DMUS_SEGF_MARKER },
  190. { ScriptConstants::AtImmediate, DMUS_SEGF_DEFAULT }, // this flag gets flipped later
  191. { 0 }
  192. };
  193. const FlagMapEntry gc_flagmapStopTransFlags[] =
  194. {
  195. { ScriptConstants::AtGrid, DMUS_COMPOSEF_GRID },
  196. { ScriptConstants::AtBeat, DMUS_COMPOSEF_BEAT },
  197. { ScriptConstants::AtMeasure, DMUS_COMPOSEF_MEASURE },
  198. { ScriptConstants::AtMarker, DMUS_COMPOSEF_MARKER },
  199. { ScriptConstants::AtImmediate, DMUS_COMPOSEF_IMMEDIATE },
  200. { 0 }
  201. };
  202. HRESULT
  203. CAutDirectMusicSegment::Stop(AutDispatchDecodedParams *paddp)
  204. {
  205. LONG lFlags = paddp->params[0].lVal;
  206. HRESULT hr = S_OK;
  207. IDirectMusicPerformance8 *pPerformance = CActiveScriptManager::GetCurrentPerformanceWEAK();
  208. if (lFlags & ScriptConstants::PlayEnd)
  209. {
  210. // do a transition to silence
  211. DWORD dwFlags = MapFlags(lFlags, gc_flagmapStopTransFlags);
  212. // Always play the entire transition instead of doing the old (slightly strange) 1 bar / long stuff.
  213. // Also, always use an embedded audio path if one exists.
  214. dwFlags |= (DMUS_COMPOSEF_ENTIRE_TRANSITION | DMUS_COMPOSEF_USE_AUDIOPATH);
  215. IDirectMusicComposer8 *pComposer = CActiveScriptManager::GetComposerWEAK();
  216. hr = pComposer->AutoTransition(pPerformance, NULL, DMUS_COMMANDT_END, dwFlags, NULL, NULL, NULL, NULL);
  217. }
  218. else
  219. {
  220. DWORD dwFlags = MapFlags(lFlags, gc_flagmapStop);
  221. // Reverse the default flag because our flag means the opposite. Default is the default and immediate is the flag.
  222. dwFlags ^= DMUS_SEGF_DEFAULT;
  223. __int64 i64IntendedStartTime;
  224. DWORD dwIntendedStartTimeFlags;
  225. CActiveScriptManager::GetCurrentTimingContext(&i64IntendedStartTime, &dwIntendedStartTimeFlags);
  226. hr = pPerformance->Stop(m_pITarget, NULL, i64IntendedStartTime, dwFlags | dwIntendedStartTimeFlags);
  227. }
  228. return hr;
  229. }
  230. HRESULT
  231. CAutDirectMusicSegment::Recompose(AutDispatchDecodedParams *paddp)
  232. {
  233. IDirectMusicComposer8 *pComposer = CActiveScriptManager::GetComposerWEAK();
  234. IDirectMusicComposer8P *pComposerP = NULL;
  235. HRESULT hr = pComposer->QueryInterface(IID_IDirectMusicComposer8P, (void**)&pComposerP);
  236. if (SUCCEEDED(hr))
  237. {
  238. hr = pComposerP->ComposeSegmentFromTemplateEx(NULL, m_pITarget, 0, 0, NULL, NULL);
  239. pComposerP->Release();
  240. }
  241. return hr;
  242. }
  243. HRESULT
  244. CAutDirectMusicSegment::DownloadOrUnload(bool fDownload, AutDispatchDecodedParams *paddp)
  245. {
  246. IUnknown *pAudioPathOrPerf = reinterpret_cast<IDirectMusicAudioPath*>(paddp->params[0].iVal);
  247. if (!pAudioPathOrPerf)
  248. pAudioPathOrPerf = CActiveScriptManager::GetCurrentPerformanceWEAK();
  249. return fDownload
  250. ? m_pITarget->Download(pAudioPathOrPerf)
  251. : m_pITarget->Unload(pAudioPathOrPerf);
  252. }