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.

361 lines
12 KiB

  1. /****************************************************************************
  2. *
  3. * File: testmus.cpp
  4. * Project: DxDiag (DirectX Diagnostic Tool)
  5. * Author: Mike Anderson (manders@microsoft.com)
  6. * Purpose: Test DMusic functionality on this machine
  7. *
  8. * (C) Copyright 1998 Microsoft Corp. All rights reserved.
  9. *
  10. ****************************************************************************/
  11. #include <Windows.h>
  12. #include <multimon.h>
  13. #include <dmusicc.h>
  14. #include <dmusici.h>
  15. #include "reginfo.h"
  16. #include "sysinfo.h"
  17. #include "dispinfo.h"
  18. #include "musinfo.h"
  19. #include "testmus.h"
  20. #include "resource.h"
  21. #ifndef ReleasePpo
  22. #define ReleasePpo(ppo) \
  23. if (*(ppo) != NULL) \
  24. { \
  25. (*(ppo))->Release(); \
  26. *(ppo) = NULL; \
  27. } \
  28. else (VOID)0
  29. #endif
  30. enum TESTID
  31. {
  32. TESTID_COINITIALIZE = 1,
  33. TESTID_CREATEDMLOADER,
  34. TESTID_CREATEDMPERF,
  35. TESTID_INITPERF,
  36. TESTID_CREATEPORT,
  37. TESTID_ACTIVATEPORT,
  38. TESTID_SETAUTODOWNLOAD,
  39. TESTID_ADDPORT,
  40. TESTID_ASSIGNPCHANNELBLOCK,
  41. TESTID_SPEWRESOURCETOFILE,
  42. TESTID_SETSEARCHDIRECTORY,
  43. TESTID_LOADERGETOBJECT,
  44. TESTID_PLAYSEGMENT,
  45. };
  46. BOOL BTranslateError(HRESULT hr, TCHAR* psz, BOOL bEnglish = FALSE); // from main.cpp (yuck)
  47. static HRESULT SpewResourceToFile(TCHAR* pszResType, LONG idRes, TCHAR* pszFileName);
  48. static HRESULT LoadSegment( BOOL fUseCWD );
  49. static VOID DeleteTempFile(TCHAR* pszFileName);
  50. /****************************************************************************
  51. *
  52. * TestMusic
  53. *
  54. ****************************************************************************/
  55. VOID TestMusic(HWND hwndMain, MusicInfo* pMusicInfo)
  56. {
  57. HRESULT hr;
  58. MusicPort* pMusicPort = NULL;
  59. IDirectMusicLoader* pLoader = NULL;
  60. IDirectMusicPerformance* pPerformance = NULL;
  61. IDirectMusic* pdm = NULL;
  62. IDirectMusicPort* pPort = NULL;
  63. IDirectMusicSegment* pSegment = NULL;
  64. BOOL bComInitialized = FALSE;
  65. TCHAR szFmt[300];
  66. TCHAR sz[300];
  67. TCHAR szTitle[100];
  68. if (pMusicInfo == NULL)
  69. return;
  70. // Determine pMusicPort of port to test:
  71. for (pMusicPort = pMusicInfo->m_pMusicPortFirst; pMusicPort != NULL; pMusicPort = pMusicPort->m_pMusicPortNext)
  72. {
  73. if (pMusicPort->m_guid == pMusicInfo->m_guidMusicPortTest)
  74. break;
  75. }
  76. if (pMusicPort == NULL)
  77. return;
  78. LoadString(NULL, IDS_APPFULLNAME, szTitle, 100);
  79. LoadString(NULL, IDS_STARTDMUSICTEST, szFmt, 300);
  80. wsprintf(sz, szFmt, pMusicPort->m_szDescription);
  81. if (IDNO == MessageBox(hwndMain, sz, szTitle, MB_YESNO))
  82. return;
  83. // Remove info from any previous test:
  84. ZeroMemory(&pMusicInfo->m_testResult, sizeof(TestResult));
  85. pMusicInfo->m_testResult.m_bStarted = TRUE;
  86. // Initialize COM
  87. if (FAILED(hr = CoInitialize(NULL)))
  88. {
  89. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_COINITIALIZE;
  90. pMusicInfo->m_testResult.m_hr = hr;
  91. goto LEnd;
  92. }
  93. bComInitialized = TRUE;
  94. // Create performance object
  95. if (FAILED(hr = CoCreateInstance(CLSID_DirectMusicPerformance, NULL,
  96. CLSCTX_INPROC, IID_IDirectMusicPerformance, (VOID**)&pPerformance)))
  97. {
  98. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_CREATEDMPERF;
  99. pMusicInfo->m_testResult.m_hr = hr;
  100. goto LEnd;
  101. }
  102. // Initialize the performance -- also creates DirectMusic object
  103. if (FAILED(hr = pPerformance->Init(&pdm, NULL, hwndMain)))
  104. {
  105. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_INITPERF;
  106. pMusicInfo->m_testResult.m_hr = hr;
  107. goto LEnd;
  108. }
  109. // Create a port using the user-specified GUID
  110. DMUS_PORTPARAMS portParams;
  111. ZeroMemory(&portParams, sizeof(portParams));
  112. portParams.dwSize = sizeof(portParams);
  113. portParams.dwValidParams = DMUS_PORTPARAMS_EFFECTS | DMUS_PORTPARAMS_CHANNELGROUPS |
  114. DMUS_PORTPARAMS_AUDIOCHANNELS;
  115. portParams.dwEffectFlags = DMUS_EFFECT_REVERB;
  116. portParams.dwChannelGroups = pMusicPort->m_dwMaxChannelGroups;
  117. portParams.dwAudioChannels = pMusicPort->m_dwMaxAudioChannels;
  118. if (FAILED(hr = pdm->CreatePort(pMusicPort->m_guid, &portParams, &pPort, NULL)))
  119. {
  120. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_CREATEPORT;
  121. pMusicInfo->m_testResult.m_hr = hr;
  122. goto LEnd;
  123. }
  124. // Activate the port
  125. if (FAILED(hr = pPort->Activate(TRUE)))
  126. {
  127. // Bug 21677: catch case where user has no sound card
  128. if (hr == DSERR_NODRIVER && !pMusicPort->m_bExternal)
  129. {
  130. LoadString(NULL, IDS_NOSOUNDDRIVER, sz, 300);
  131. MessageBox(hwndMain, sz, szTitle, MB_OK);
  132. }
  133. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_ACTIVATEPORT;
  134. pMusicInfo->m_testResult.m_hr = hr;
  135. goto LEnd;
  136. }
  137. // Set autodownloading to be on
  138. BOOL fAutoDownload;
  139. fAutoDownload = TRUE;
  140. if (FAILED(hr = pPerformance->SetGlobalParam(GUID_PerfAutoDownload,
  141. &fAutoDownload, sizeof(BOOL))))
  142. {
  143. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_SETAUTODOWNLOAD;
  144. pMusicInfo->m_testResult.m_hr = hr;
  145. goto LEnd;
  146. }
  147. // Add the port to the performance
  148. if (FAILED(hr = pPerformance->AddPort(pPort)))
  149. {
  150. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_ADDPORT;
  151. pMusicInfo->m_testResult.m_hr = hr;
  152. goto LEnd;
  153. }
  154. if (FAILED(hr = pPerformance->AssignPChannelBlock(0, pPort, 1)))
  155. {
  156. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_ASSIGNPCHANNELBLOCK;
  157. pMusicInfo->m_testResult.m_hr = hr;
  158. goto LEnd;
  159. }
  160. if (FAILED(hr = SpewResourceToFile(TEXT("SGMT"), IDR_TSTSGMT, TEXT("Edge.sgt"))))
  161. {
  162. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_SPEWRESOURCETOFILE;
  163. pMusicInfo->m_testResult.m_hr = hr;
  164. goto LEnd;
  165. }
  166. if (FAILED(hr = SpewResourceToFile(TEXT("STYL"), IDR_TSTSTYL, TEXT("Edge.sty"))))
  167. {
  168. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_SPEWRESOURCETOFILE;
  169. pMusicInfo->m_testResult.m_hr = hr;
  170. goto LEnd;
  171. }
  172. // Create loader object
  173. if (FAILED(hr = CoCreateInstance(CLSID_DirectMusicLoader, NULL,
  174. CLSCTX_INPROC, IID_IDirectMusicLoader, (VOID**)&pLoader)))
  175. {
  176. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_CREATEDMLOADER;
  177. pMusicInfo->m_testResult.m_hr = hr;
  178. goto LEnd;
  179. }
  180. // Set search path to temp dir to find segment and style:
  181. WCHAR wszDir[MAX_PATH];
  182. TCHAR szTempPath[MAX_PATH];
  183. GetTempPath(MAX_PATH, szTempPath);
  184. szTempPath[lstrlen(szTempPath) - 1] = '\0';
  185. #ifdef UNICODE
  186. lstrcpy(wszDir, szTempPath);
  187. #else
  188. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szTempPath, -1, wszDir, MAX_PATH);
  189. #endif
  190. if (FAILED(hr = pLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, wszDir, FALSE)))
  191. {
  192. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_SETSEARCHDIRECTORY;
  193. pMusicInfo->m_testResult.m_hr = hr;
  194. goto LEnd;
  195. }
  196. // Load the segment
  197. // now load the segment file.
  198. // sections load as type Segment, as do MIDI files, for example.
  199. DMUS_OBJECTDESC objDesc; // Object descriptor for pLoader->GetObject()
  200. objDesc.guidClass = CLSID_DirectMusicSegment;
  201. objDesc.dwSize = sizeof(DMUS_OBJECTDESC);
  202. wcscpy(objDesc.wszFileName, L"edge.sgt");
  203. objDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
  204. if (FAILED(hr = pLoader->GetObject(&objDesc, IID_IDirectMusicSegment, (VOID**)&pSegment)))
  205. {
  206. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_LOADERGETOBJECT;
  207. pMusicInfo->m_testResult.m_hr = hr;
  208. goto LEnd;
  209. }
  210. // Play the segment and wait. The DMUS_SEGF_BEAT indicates to play on the
  211. // next beat if there is a segment currently playing. The first 0 indicates
  212. // to play (on the next beat from) now.
  213. // The final NULL means do not return an IDirectMusicSegmentState* in
  214. // the last parameter.
  215. if (FAILED(hr = pPerformance->PlaySegment(pSegment, DMUS_SEGF_BEAT, 0, NULL)))
  216. {
  217. pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_PLAYSEGMENT;
  218. pMusicInfo->m_testResult.m_hr = hr;
  219. goto LEnd;
  220. }
  221. if (pMusicPort->m_bExternal)
  222. LoadString(NULL, IDS_EXTERNALMUSICPLAYING, sz, 300);
  223. else
  224. LoadString(NULL, IDS_MUSICPLAYING, sz, 300);
  225. MessageBox(hwndMain, sz, szTitle, MB_OK);
  226. pPerformance->Stop(pSegment, NULL, 0, 0);
  227. LEnd:
  228. DeleteTempFile(TEXT("Edge.sgt"));
  229. DeleteTempFile(TEXT("Edge.sty"));
  230. ReleasePpo(&pdm);
  231. ReleasePpo(&pPort);
  232. if (pPerformance != NULL)
  233. pPerformance->CloseDown();
  234. ReleasePpo(&pPerformance);
  235. ReleasePpo(&pLoader);
  236. if (bComInitialized)
  237. {
  238. // Release COM
  239. CoUninitialize();
  240. }
  241. if (pMusicInfo->m_testResult.m_iStepThatFailed == 0)
  242. {
  243. LoadString(NULL, IDS_TESTSSUCCESSFUL, sz, 300);
  244. lstrcpy(pMusicInfo->m_testResult.m_szDescription, sz);
  245. LoadString(NULL, IDS_TESTSSUCCESSFUL_ENGLISH, sz, 300);
  246. lstrcpy(pMusicInfo->m_testResult.m_szDescriptionEnglish, sz);
  247. }
  248. else
  249. {
  250. TCHAR szDesc[200];
  251. TCHAR szError[200];
  252. if (0 == LoadString(NULL, IDS_FIRSTDMUSICTESTERROR +
  253. pMusicInfo->m_testResult.m_iStepThatFailed - 1, szDesc, 200))
  254. {
  255. LoadString(NULL, IDS_UNKNOWNERROR, sz, 300);
  256. lstrcpy(szDesc, sz);
  257. }
  258. LoadString(NULL, IDS_FAILUREFMT, sz, 300);
  259. BTranslateError(pMusicInfo->m_testResult.m_hr, szError);
  260. wsprintf(pMusicInfo->m_testResult.m_szDescription, sz,
  261. pMusicInfo->m_testResult.m_iStepThatFailed,
  262. szDesc, pMusicInfo->m_testResult.m_hr, szError);
  263. // Nonlocalized version:
  264. if (0 == LoadString(NULL, IDS_FIRSTDMUSICTESTERROR_ENGLISH +
  265. pMusicInfo->m_testResult.m_iStepThatFailed - 1, szDesc, 200))
  266. {
  267. LoadString(NULL, IDS_UNKNOWNERROR_ENGLISH, sz, 300);
  268. lstrcpy(szDesc, sz);
  269. }
  270. LoadString(NULL, IDS_FAILUREFMT_ENGLISH, sz, 300);
  271. BTranslateError(pMusicInfo->m_testResult.m_hr, szError, TRUE);
  272. wsprintf(pMusicInfo->m_testResult.m_szDescriptionEnglish, sz,
  273. pMusicInfo->m_testResult.m_iStepThatFailed,
  274. szDesc, pMusicInfo->m_testResult.m_hr, szError);
  275. }
  276. }
  277. /****************************************************************************
  278. *
  279. * SpewResourceToFile
  280. *
  281. ****************************************************************************/
  282. HRESULT SpewResourceToFile(TCHAR* pszResType, LONG idRes, TCHAR* pszFileName)
  283. {
  284. TCHAR szTempPath[MAX_PATH];
  285. HRSRC hResInfo = NULL;
  286. HGLOBAL hResData = NULL;
  287. BYTE* pbData = NULL;
  288. HANDLE hfile;
  289. DWORD numBytes;
  290. DWORD numBytesWritten;
  291. GetTempPath(MAX_PATH, szTempPath);
  292. lstrcat(szTempPath, pszFileName);
  293. if (NULL == (hResInfo = FindResource(NULL, MAKEINTRESOURCE(idRes), pszResType)))
  294. return E_FAIL;
  295. numBytes = SizeofResource(NULL, hResInfo);
  296. if (NULL == (hResData = LoadResource(NULL, hResInfo)))
  297. return E_FAIL;
  298. if (NULL == (pbData = (BYTE*)LockResource(hResData)))
  299. return E_FAIL;
  300. hfile = CreateFile(szTempPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  301. FILE_ATTRIBUTE_TEMPORARY, NULL);
  302. if (hfile == INVALID_HANDLE_VALUE)
  303. return E_FAIL;
  304. WriteFile(hfile, pbData, numBytes, &numBytesWritten, NULL);
  305. CloseHandle(hfile);
  306. return S_OK;
  307. }
  308. /****************************************************************************
  309. *
  310. * DeleteTempFile
  311. *
  312. ****************************************************************************/
  313. VOID DeleteTempFile(TCHAR* pszFileName)
  314. {
  315. TCHAR szTempPath[MAX_PATH];
  316. GetTempPath(MAX_PATH, szTempPath);
  317. lstrcat(szTempPath, pszFileName);
  318. DeleteFile(szTempPath);
  319. }