367 lines
12 KiB
C++
367 lines
12 KiB
C++
/****************************************************************************
|
|
*
|
|
* File: testmus.cpp
|
|
* Project: DxDiag (DirectX Diagnostic Tool)
|
|
* Author: Mike Anderson (manders@microsoft.com)
|
|
* Purpose: Test DMusic functionality on this machine
|
|
*
|
|
* (C) Copyright 1998 Microsoft Corp. All rights reserved.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <Windows.h>
|
|
#include <multimon.h>
|
|
#include <dmusicc.h>
|
|
#include <dmusici.h>
|
|
#include "reginfo.h"
|
|
#include "sysinfo.h"
|
|
#include "dispinfo.h"
|
|
#include "musinfo.h"
|
|
#include "testmus.h"
|
|
#include "resource.h"
|
|
|
|
#ifndef ReleasePpo
|
|
#define ReleasePpo(ppo) \
|
|
if (*(ppo) != NULL) \
|
|
{ \
|
|
(*(ppo))->Release(); \
|
|
*(ppo) = NULL; \
|
|
} \
|
|
else (VOID)0
|
|
#endif
|
|
|
|
enum TESTID
|
|
{
|
|
TESTID_COINITIALIZE = 1,
|
|
TESTID_CREATEDMLOADER,
|
|
TESTID_CREATEDMPERF,
|
|
TESTID_INITPERF,
|
|
TESTID_CREATEPORT,
|
|
TESTID_ACTIVATEPORT,
|
|
TESTID_SETAUTODOWNLOAD,
|
|
TESTID_ADDPORT,
|
|
TESTID_ASSIGNPCHANNELBLOCK,
|
|
TESTID_SPEWRESOURCETOFILE,
|
|
TESTID_SETSEARCHDIRECTORY,
|
|
TESTID_LOADERGETOBJECT,
|
|
TESTID_PLAYSEGMENT,
|
|
};
|
|
|
|
BOOL BTranslateError(HRESULT hr, TCHAR* psz, BOOL bEnglish = FALSE); // from main.cpp (yuck)
|
|
|
|
static HRESULT SpewResourceToFile(TCHAR* pszResType, LONG idRes, TCHAR* pszFileName);
|
|
static HRESULT LoadSegment( BOOL fUseCWD );
|
|
static VOID DeleteTempFile(TCHAR* pszFileName);
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* TestMusic
|
|
*
|
|
****************************************************************************/
|
|
VOID TestMusic(HWND hwndMain, MusicInfo* pMusicInfo)
|
|
{
|
|
HRESULT hr;
|
|
MusicPort* pMusicPort = NULL;
|
|
IDirectMusicLoader* pLoader = NULL;
|
|
IDirectMusicPerformance* pPerformance = NULL;
|
|
IDirectMusic* pdm = NULL;
|
|
IDirectMusicPort* pPort = NULL;
|
|
IDirectMusicSegment* pSegment = NULL;
|
|
BOOL bComInitialized = FALSE;
|
|
TCHAR szFmt[300];
|
|
TCHAR sz[300];
|
|
TCHAR szTitle[100];
|
|
|
|
if (pMusicInfo == NULL)
|
|
return;
|
|
|
|
// Determine pMusicPort of port to test:
|
|
for (pMusicPort = pMusicInfo->m_pMusicPortFirst; pMusicPort != NULL; pMusicPort = pMusicPort->m_pMusicPortNext)
|
|
{
|
|
if (pMusicPort->m_guid == pMusicInfo->m_guidMusicPortTest)
|
|
break;
|
|
}
|
|
if (pMusicPort == NULL)
|
|
return;
|
|
|
|
LoadString(NULL, IDS_APPFULLNAME, szTitle, 100);
|
|
LoadString(NULL, IDS_STARTDMUSICTEST, szFmt, 300);
|
|
wsprintf(sz, szFmt, pMusicPort->m_szDescription);
|
|
if (IDNO == MessageBox(hwndMain, sz, szTitle, MB_YESNO))
|
|
return;
|
|
|
|
// Remove info from any previous test:
|
|
ZeroMemory(&pMusicInfo->m_testResult, sizeof(TestResult));
|
|
|
|
pMusicInfo->m_testResult.m_bStarted = TRUE;
|
|
|
|
// Initialize COM
|
|
if (FAILED(hr = CoInitialize(NULL)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_COINITIALIZE;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
bComInitialized = TRUE;
|
|
|
|
// Create performance object
|
|
if (FAILED(hr = CoCreateInstance(CLSID_DirectMusicPerformance, NULL,
|
|
CLSCTX_INPROC, IID_IDirectMusicPerformance, (VOID**)&pPerformance)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_CREATEDMPERF;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Initialize the performance -- also creates DirectMusic object
|
|
if (FAILED(hr = pPerformance->Init(&pdm, NULL, hwndMain)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_INITPERF;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Create a port using the user-specified GUID
|
|
DMUS_PORTPARAMS portParams;
|
|
ZeroMemory(&portParams, sizeof(portParams));
|
|
portParams.dwSize = sizeof(portParams);
|
|
portParams.dwValidParams = DMUS_PORTPARAMS_EFFECTS | DMUS_PORTPARAMS_CHANNELGROUPS |
|
|
DMUS_PORTPARAMS_AUDIOCHANNELS;
|
|
portParams.dwEffectFlags = DMUS_EFFECT_REVERB;
|
|
portParams.dwChannelGroups = pMusicPort->m_dwMaxChannelGroups;
|
|
portParams.dwAudioChannels = pMusicPort->m_dwMaxAudioChannels;
|
|
if (FAILED(hr = pdm->CreatePort(pMusicPort->m_guid, &portParams, &pPort, NULL)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_CREATEPORT;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Activate the port
|
|
if (FAILED(hr = pPort->Activate(TRUE)))
|
|
{
|
|
// Bug 21677: catch case where user has no sound card
|
|
if (hr == DSERR_NODRIVER && !pMusicPort->m_bExternal)
|
|
{
|
|
LoadString(NULL, IDS_NOSOUNDDRIVER, sz, 300);
|
|
MessageBox(hwndMain, sz, szTitle, MB_OK);
|
|
}
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_ACTIVATEPORT;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Set autodownloading to be on
|
|
BOOL fAutoDownload;
|
|
fAutoDownload = TRUE;
|
|
if (FAILED(hr = pPerformance->SetGlobalParam(GUID_PerfAutoDownload,
|
|
&fAutoDownload, sizeof(BOOL))))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_SETAUTODOWNLOAD;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Add the port to the performance
|
|
if (FAILED(hr = pPerformance->AddPort(pPort)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_ADDPORT;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
if (FAILED(hr = pPerformance->AssignPChannelBlock(0, pPort, 1)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_ASSIGNPCHANNELBLOCK;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
if (FAILED(hr = SpewResourceToFile(TEXT("SGMT"), IDR_TSTSGMT, TEXT("Edge.sgt"))))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_SPEWRESOURCETOFILE;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
if (FAILED(hr = SpewResourceToFile(TEXT("STYL"), IDR_TSTSTYL, TEXT("Edge.sty"))))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_SPEWRESOURCETOFILE;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Create loader object
|
|
if (FAILED(hr = CoCreateInstance(CLSID_DirectMusicLoader, NULL,
|
|
CLSCTX_INPROC, IID_IDirectMusicLoader, (VOID**)&pLoader)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_CREATEDMLOADER;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Set search path to temp dir to find segment and style:
|
|
WCHAR wszDir[MAX_PATH];
|
|
TCHAR szTempPath[MAX_PATH];
|
|
GetTempPath(MAX_PATH, szTempPath);
|
|
if( lstrlen(szTempPath) > 0 )
|
|
szTempPath[lstrlen(szTempPath) - 1] = '\0';
|
|
#ifdef UNICODE
|
|
lstrcpy(wszDir, szTempPath);
|
|
#else
|
|
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szTempPath, -1, wszDir, MAX_PATH);
|
|
#endif
|
|
if (FAILED(hr = pLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, wszDir, FALSE)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_SETSEARCHDIRECTORY;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Load the segment
|
|
// now load the segment file.
|
|
// sections load as type Segment, as do MIDI files, for example.
|
|
DMUS_OBJECTDESC objDesc; // Object descriptor for pLoader->GetObject()
|
|
objDesc.guidClass = CLSID_DirectMusicSegment;
|
|
objDesc.dwSize = sizeof(DMUS_OBJECTDESC);
|
|
wcscpy(objDesc.wszFileName, L"edge.sgt");
|
|
objDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
|
|
if (FAILED(hr = pLoader->GetObject(&objDesc, IID_IDirectMusicSegment, (VOID**)&pSegment)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_LOADERGETOBJECT;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
// Play the segment and wait. The DMUS_SEGF_BEAT indicates to play on the
|
|
// next beat if there is a segment currently playing. The first 0 indicates
|
|
// to play (on the next beat from) now.
|
|
// The final NULL means do not return an IDirectMusicSegmentState* in
|
|
// the last parameter.
|
|
if (FAILED(hr = pPerformance->PlaySegment(pSegment, DMUS_SEGF_BEAT, 0, NULL)))
|
|
{
|
|
pMusicInfo->m_testResult.m_iStepThatFailed = TESTID_PLAYSEGMENT;
|
|
pMusicInfo->m_testResult.m_hr = hr;
|
|
goto LEnd;
|
|
}
|
|
|
|
if (pMusicPort->m_bExternal)
|
|
LoadString(NULL, IDS_EXTERNALMUSICPLAYING, sz, 300);
|
|
else
|
|
LoadString(NULL, IDS_MUSICPLAYING, sz, 300);
|
|
MessageBox(hwndMain, sz, szTitle, MB_OK);
|
|
|
|
pPerformance->Stop(pSegment, NULL, 0, 0);
|
|
|
|
LEnd:
|
|
DeleteTempFile(TEXT("Edge.sgt"));
|
|
DeleteTempFile(TEXT("Edge.sty"));
|
|
|
|
ReleasePpo(&pdm);
|
|
ReleasePpo(&pPort);
|
|
if (pPerformance != NULL)
|
|
pPerformance->CloseDown();
|
|
ReleasePpo(&pPerformance);
|
|
ReleasePpo(&pLoader);
|
|
|
|
if (bComInitialized)
|
|
{
|
|
// Release COM
|
|
CoUninitialize();
|
|
}
|
|
|
|
if (pMusicInfo->m_testResult.m_iStepThatFailed == 0)
|
|
{
|
|
LoadString(NULL, IDS_TESTSSUCCESSFUL, sz, 300);
|
|
lstrcpy(pMusicInfo->m_testResult.m_szDescription, sz);
|
|
|
|
LoadString(NULL, IDS_TESTSSUCCESSFUL_ENGLISH, sz, 300);
|
|
lstrcpy(pMusicInfo->m_testResult.m_szDescriptionEnglish, sz);
|
|
}
|
|
else
|
|
{
|
|
TCHAR szDesc[300];
|
|
TCHAR szError[300];
|
|
if (0 == LoadString(NULL, IDS_FIRSTDMUSICTESTERROR +
|
|
pMusicInfo->m_testResult.m_iStepThatFailed - 1, szDesc, 200))
|
|
{
|
|
LoadString(NULL, IDS_UNKNOWNERROR, sz, 300);
|
|
lstrcpy(szDesc, sz);
|
|
}
|
|
LoadString(NULL, IDS_FAILUREFMT, sz, 300);
|
|
BTranslateError(pMusicInfo->m_testResult.m_hr, szError);
|
|
wsprintf(pMusicInfo->m_testResult.m_szDescription, sz,
|
|
pMusicInfo->m_testResult.m_iStepThatFailed,
|
|
szDesc, pMusicInfo->m_testResult.m_hr, szError);
|
|
|
|
// Nonlocalized version:
|
|
if (0 == LoadString(NULL, IDS_FIRSTDMUSICTESTERROR_ENGLISH +
|
|
pMusicInfo->m_testResult.m_iStepThatFailed - 1, szDesc, 200))
|
|
{
|
|
LoadString(NULL, IDS_UNKNOWNERROR_ENGLISH, sz, 300);
|
|
lstrcpy(szDesc, sz);
|
|
}
|
|
LoadString(NULL, IDS_FAILUREFMT_ENGLISH, sz, 300);
|
|
BTranslateError(pMusicInfo->m_testResult.m_hr, szError, TRUE);
|
|
wsprintf(pMusicInfo->m_testResult.m_szDescriptionEnglish, sz,
|
|
pMusicInfo->m_testResult.m_iStepThatFailed,
|
|
szDesc, pMusicInfo->m_testResult.m_hr, szError);
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* SpewResourceToFile
|
|
*
|
|
****************************************************************************/
|
|
HRESULT SpewResourceToFile(TCHAR* pszResType, LONG idRes, TCHAR* pszFileName)
|
|
{
|
|
TCHAR szTempPath[MAX_PATH];
|
|
HRSRC hResInfo = NULL;
|
|
HGLOBAL hResData = NULL;
|
|
BYTE* pbData = NULL;
|
|
HANDLE hfile;
|
|
DWORD numBytes;
|
|
DWORD numBytesWritten;
|
|
|
|
GetTempPath(MAX_PATH, szTempPath);
|
|
if( lstrlen(szTempPath) + lstrlen(pszFileName) < MAX_PATH )
|
|
lstrcat(szTempPath, pszFileName);
|
|
szTempPath[MAX_PATH-1]=0;
|
|
if (NULL == (hResInfo = FindResource(NULL, MAKEINTRESOURCE(idRes), pszResType)))
|
|
return E_FAIL;
|
|
numBytes = SizeofResource(NULL, hResInfo);
|
|
if (NULL == (hResData = LoadResource(NULL, hResInfo)))
|
|
return E_FAIL;
|
|
if (NULL == (pbData = (BYTE*)LockResource(hResData)))
|
|
return E_FAIL;
|
|
|
|
hfile = CreateFile(szTempPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_TEMPORARY, NULL);
|
|
if (hfile == INVALID_HANDLE_VALUE)
|
|
return E_FAIL;
|
|
WriteFile(hfile, pbData, numBytes, &numBytesWritten, NULL);
|
|
CloseHandle(hfile);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* DeleteTempFile
|
|
*
|
|
****************************************************************************/
|
|
VOID DeleteTempFile(TCHAR* pszFileName)
|
|
{
|
|
TCHAR szTempPath[MAX_PATH];
|
|
|
|
GetTempPath(MAX_PATH, szTempPath);
|
|
if( lstrlen(szTempPath) + lstrlen(pszFileName) < MAX_PATH )
|
|
lstrcat(szTempPath, pszFileName);
|
|
szTempPath[MAX_PATH-1]=0;
|
|
DeleteFile(szTempPath);
|
|
}
|