레거시 Windows 멀티미디어 애플리케이션에 대한 디바이스 역할
참고
MMDevice API는 디바이스 역할을 지원합니다. 그러나 Windows Vista의 사용자 인터페이스는 이 기능에 대한 지원을 구현하지 않습니다. 디바이스 역할에 대한 사용자 인터페이스 지원은 이후 버전의 Windows에서 구현될 수 있습니다. 자세한 내용은 Windows Vista의 디바이스 역할을 참조하세요.
레거시 Windows 멀티미디어 waveOutXxx 및 waveInXxx 함수는 애플리케이션이 사용자가 특정 디바이스 역할에 할당한 오디오 엔드포인트 디바이스를 선택할 수 있는 수단을 제공하지 않습니다. 그러나 Windows Vista에서는 핵심 오디오 API를 Windows 멀티미디어 애플리케이션과 함께 사용하여 디바이스 역할에 따라 디바이스를 선택할 수 있습니다. 예를 들어 MMDevice API의 도움으로 waveOutXxx 애플리케이션은 역할에 할당된 오디오 엔드포인트 디바이스를 식별하고, 해당 파형 출력 디바이스를 식별하고, waveOutOpen 함수를 호출하여 디바이스의 instance 열 수 있습니다. waveOutXxx 및 waveInXxx에 대한 자세한 내용은 Windows SDK 설명서를 참조하세요.
다음 코드 예제에서는 특정 디바이스 역할에 할당된 렌더링 엔드포인트 디바이스에 대한 파형 디바이스 ID를 가져오는 방법을 보여 줍니다.
//-----------------------------------------------------------
// This function gets the waveOut ID of the audio endpoint
// device that is currently assigned to the specified device
// role. The caller can use the waveOut ID to open the
// waveOut device that corresponds to the endpoint device.
//-----------------------------------------------------------
#define EXIT_ON_ERROR(hres) \
if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; }
HRESULT GetWaveOutId(ERole role, int *pWaveOutId)
{
HRESULT hr;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
WCHAR *pstrEndpointIdKey = NULL;
WCHAR *pstrEndpointId = NULL;
if (pWaveOutId == NULL)
{
return E_POINTER;
}
// Create an audio endpoint device enumerator.
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator),
(void**)&pEnumerator);
EXIT_ON_ERROR(hr)
// Get the audio endpoint device that the user has
// assigned to the specified device role.
hr = pEnumerator->GetDefaultAudioEndpoint(eRender, role,
&pDevice);
EXIT_ON_ERROR(hr)
// Get the endpoint ID string of the audio endpoint device.
hr = pDevice->GetId(&pstrEndpointIdKey);
EXIT_ON_ERROR(hr)
// Get the size of the endpoint ID string.
size_t cbEndpointIdKey;
hr = StringCbLength(pstrEndpointIdKey,
STRSAFE_MAX_CCH * sizeof(WCHAR),
&cbEndpointIdKey);
EXIT_ON_ERROR(hr)
// Include terminating null in string size.
cbEndpointIdKey += sizeof(WCHAR);
// Allocate a buffer for a second string of the same size.
pstrEndpointId = (WCHAR*)CoTaskMemAlloc(cbEndpointIdKey);
if (pstrEndpointId == NULL)
{
EXIT_ON_ERROR(hr = E_OUTOFMEMORY)
}
// Each for-loop iteration below compares the endpoint ID
// string of the audio endpoint device to the endpoint ID
// string of an enumerated waveOut device. If the strings
// match, then we've found the waveOut device that is
// assigned to the specified device role.
int waveOutId;
int cWaveOutDevices = waveOutGetNumDevs();
for (waveOutId = 0; waveOutId < cWaveOutDevices; waveOutId++)
{
MMRESULT mmr;
size_t cbEndpointId;
// Get the size (including the terminating null) of
// the endpoint ID string of the waveOut device.
mmr = waveOutMessage((HWAVEOUT)IntToPtr(waveOutId),
DRV_QUERYFUNCTIONINSTANCEIDSIZE,
(DWORD_PTR)&cbEndpointId, NULL);
if (mmr != MMSYSERR_NOERROR ||
cbEndpointIdKey != cbEndpointId) // do sizes match?
{
continue; // not a matching device
}
// Get the endpoint ID string for this waveOut device.
mmr = waveOutMessage((HWAVEOUT)IntToPtr(waveOutId),
DRV_QUERYFUNCTIONINSTANCEID,
(DWORD_PTR)pstrEndpointId,
cbEndpointId);
if (mmr != MMSYSERR_NOERROR)
{
continue;
}
// Check whether the endpoint ID string of this waveOut
// device matches that of the audio endpoint device.
if (lstrcmpi(pstrEndpointId, pstrEndpointIdKey) == 0)
{
*pWaveOutId = waveOutId; // found match
hr = S_OK;
break;
}
}
if (waveOutId == cWaveOutDevices)
{
// We reached the end of the for-loop above without
// finding a waveOut device with a matching endpoint
// ID string. This behavior is quite unexpected.
hr = E_UNEXPECTED;
}
Exit:
SAFE_RELEASE(pEnumerator);
SAFE_RELEASE(pDevice);
CoTaskMemFree(pstrEndpointIdKey); // NULL pointer okay
CoTaskMemFree(pstrEndpointId);
return hr;
}
앞의 코드 예제에서 GetWaveOutId 함수는 디바이스 역할(eConsole, eMultimedia 또는 eCommunications)을 입력 매개 변수로 허용합니다. 두 번째 매개 변수는 함수가 지정된 역할에 할당된 파형 출력 디바이스에 대한 파형 디바이스 ID를 작성하는 포인터입니다. 그러면 애플리케이션이 이 ID로 waveOutOpen 을 호출하여 디바이스를 열 수 있습니다.
앞의 코드 예제의 기본 루프에는 waveOutMessage 함수에 대한 두 가지 호출이 포함되어 있습니다. 첫 번째 호출은 waveOutId 매개 변수로 식별되는 파형 디바이스의 엔드포인트 ID 문자열의 크기(바이트)를 검색하기 위해 DRV_QUERYFUNCTIONINSTANCEIDSIZE 메시지를 보냅니다. (엔드포인트 ID 문자열은 파형 디바이스 추상화의 기초가 되는 오디오 엔드포인트 디바이스를 식별합니다.) 이 호출에서 보고하는 크기에는 문자열 끝에 있는 종료 null 문자에 대한 공간이 포함됩니다. 프로그램은 크기 정보를 사용하여 전체 엔드포인트 ID 문자열을 포함할 수 있을 만큼 큰 버퍼를 할당할 수 있습니다.
waveOutMessage에 대한 두 번째 호출은 DRV_QUERYFUNCTIONINSTANCEID 메시지를 보내 파형 출력 디바이스의 디바이스 ID 문자열을 검색합니다. 예제 코드는 이 문자열을 지정된 디바이스 역할과 오디오 엔드포인트 디바이스의 디바이스 ID 문자열과 비교합니다. 문자열이 일치하면 함수는 파형 디바이스 ID를 pWaveOutId 매개 변수가 가리키는 위치에 씁니다. 호출자는 이 ID를 사용하여 지정된 디바이스 역할이 있는 파형 출력 디바이스를 열 수 있습니다.
Windows Vista는 DRV_QUERYFUNCTIONINSTANCEIDSIZE 및 DRV_QUERYFUNCTIONINSTANCEID 메시지를 지원합니다. Windows Server 2003, Windows XP 및 Windows 2000을 비롯한 이전 버전의 Windows에서는 지원되지 않습니다.
앞의 코드 예제의 함수는 렌더링 디바이스에 대한 파형 디바이스 ID를 가져오지만 몇 가지 수정을 통해 캡처 디바이스에 대한 파형 디바이스 ID를 가져오도록 조정할 수 있습니다. 그런 다음 애플리케이션은 이 ID로 waveInOpen 을 호출하여 디바이스를 열 수 있습니다. 이전 코드 예제를 변경하여 특정 역할에 할당된 오디오 캡처 엔드포인트 디바이스의 파형 디바이스 ID를 가져오려면 다음을 수행합니다.
- 이전 예제의 모든 waveOutXxx 함수 호출을 해당 waveInXxx 함수 호출로 바꿉다.
- 핸들 형식 HWAVEOUT을 HWAVEIN으로 변경합니다.
- ERole 열거형 상수 eRender를 eCapture로 바꿉다.
Windows Vista에서 waveOutOpen 및 waveInOpen 함수는 항상 만든 오디오 스트림을 기본 세션에 할당합니다. 세션 GUID 값으로 식별되는 프로세스별 세션은 GUID_NULL.
관련 항목