レガシ Windows マルチメディア アプリケーションのデバイス ロール
手記
MMDevice API では、デバイス ロールがサポートされています。 ただし、Windows Vista のユーザー インターフェイスでは、この機能のサポートは実装されていません。 デバイス ロールのユーザー インターフェイスのサポートは、今後のバージョンの Windows で実装される可能性があります。 詳細については、「Windows Vista でのデバイスロールの」を参照してください。
従来の Windows マルチメディア waveOutXxx および waveInXxx 関数では、ユーザーが特定の デバイス ロールに割り当てた オーディオ エンドポイント デバイスをアプリケーションで選択する手段はありません。 ただし、Windows Vista では、コア オーディオ API を Windows マルチメディア アプリケーションと組み合わせて使用して、デバイスの役割に基づいてデバイスを選択できます。 たとえば、MMDevice APIの助けを借りて、waveOutXxx アプリケーションは、ロールに割り当てられているオーディオ エンドポイント デバイスを識別し、対応する波形出力デバイスを識別し、waveOutOpen 関数を呼び出してデバイスのインスタンスを開くことができます。 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) を入力パラメーターとして受け入れます。 2 番目のパラメーターは、指定されたロールに割り当てられている波形出力デバイスの波形デバイス ID を関数が書き込むポインターです。 その後、アプリケーションはこの ID waveOutOpen を呼び出して、デバイスを開くことができます。
前のコード例のメイン ループには、waveOutMessage 関数への 2 つの呼び出しが含まれています。 最初の呼び出しでは、DRV_QUERYFUNCTIONINSTANCEIDSIZE メッセージを送信して、waveOutId パラメーターによって識別される波形デバイスの エンドポイント ID 文字列 のサイズ (バイト単位) を取得します。 (エンドポイント ID 文字列は、波形デバイスの抽象化の基になるオーディオ エンドポイント デバイスを識別します)。この呼び出しによって報告されるサイズには、文字列の末尾にある終端の null 文字の領域が含まれます。 プログラムは、サイズ情報を使用して、エンドポイント ID 文字列全体を格納するのに十分な大きさのバッファーを割り当てることができます。
waveOutMessage を する 2 回目の呼び出しでは、波形出力デバイスのデバイス ID 文字列を取得するDRV_QUERYFUNCTIONINSTANCEID メッセージが送信されます。 コード例では、この文字列を、指定されたデバイス ロールを持つオーディオ エンドポイント デバイスのデバイス ID 文字列と比較します。 文字列が一致する場合、関数は、pWaveOutId パラメーター指す場所に波形デバイス ID を書き込みます。 呼び出し元はこの 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列挙定数 eRendereCapture に置き換えます。
Windows Vista では、waveOutOpen 関数と waveInOpen 関数は、作成したオーディオ ストリームを既定のセッション (セッション GUID 値GUID_NULLで識別されるプロセス固有のセッション) に常に割り当てます。
関連トピック
-
レガシ オーディオ API との相互運用性の