Freigeben über


Geräterollen für Ältere Windows Multimedia-Anwendungen

Anmerkung

Die MMDevice-API unterstützt Geräterollen. Die Benutzeroberfläche in Windows Vista implementiert jedoch keine Unterstützung für dieses Feature. Die Unterstützung der Benutzeroberfläche für Geräterollen kann in einer zukünftigen Version von Windows implementiert werden. Weitere Informationen finden Sie unter Geräterollen in Windows Vista.

 

Die älteren Windows Multimedia waveOutXxx- und waveInXxx--Funktionen bieten keine Möglichkeit für eine Anwendung, das Audioendpunktgerät auszuwählen, dem der Benutzer einer bestimmten Geräterollezugewiesen hat. In Windows Vista können die wichtigsten Audio-APIs jedoch in Verbindung mit einer Windows-Multimediaanwendung verwendet werden, um die Geräteauswahl basierend auf der Geräterolle zu ermöglichen. Mit Hilfe der MMDevice-API-kann beispielsweise eine waveOutXxx- Anwendung das Audioendpunktgerät identifizieren, das einer Rolle zugewiesen ist, das entsprechende Waveform-Ausgabegerät identifizieren und die waveOutOpen--Funktion aufrufen, um eine Instanz des Geräts zu öffnen. Weitere Informationen zu waveOutXxx und waveInXxxfinden Sie in der Windows SDK-Dokumentation.

Das folgende Codebeispiel zeigt, wie Sie die Waveform-Geräte-ID für das Renderingendpunktgerät abrufen, das einer bestimmten Geräterolle zugewiesen ist:

//-----------------------------------------------------------
// 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;
}

Im vorherigen Codebeispiel akzeptiert die GetWaveOutId-Funktion eine Geräterolle (eConsole, eMultimedia oder eCommunications) als Eingabeparameter. Der zweite Parameter ist ein Zeiger, über den die Funktion die Waveform-Geräte-ID für das Waveform-Ausgabegerät schreibt, das der angegebenen Rolle zugewiesen ist. Die Anwendung kann dann waveOutOpen mit dieser ID aufrufen, um das Gerät zu öffnen.

Die Hauptschleife im vorherigen Codebeispiel enthält zwei Aufrufe der waveOutMessage--Funktion. Der erste Aufruf sendet eine DRV_QUERYFUNCTIONINSTANCEIDSIZE Nachricht, um die Größe der Endpunkt-ID-Zeichenfolge in Bytes des Wellenformgeräts abzurufen, das durch den waveOutId Parameter identifiziert wird. (Die Endpunkt-ID-Zeichenfolge identifiziert das Audioendpunktgerät, das die Abstraktion des Waveform-Geräts unterlies.) Die von diesem Aufruf gemeldete Größe enthält das Leerzeichen für das endende NULL-Zeichen am Ende der Zeichenfolge. Das Programm kann die Größeninformationen verwenden, um einen Puffer zuzuweisen, der groß genug ist, um die gesamte Endpunkt-ID-Zeichenfolge zu enthalten.

Der zweite Aufruf von waveOutMessage sendet eine DRV_QUERYFUNCTIONINSTANCEID Nachricht, um die Geräte-ID-Zeichenfolge des Waveform-Ausgabegeräts abzurufen. Der Beispielcode vergleicht diese Zeichenfolge mit der Geräte-ID-Zeichenfolge des Audioendpunktgeräts mit der angegebenen Geräterolle. Wenn die Zeichenfolgen übereinstimmen, schreibt die Funktion die Waveform-Geräte-ID an die Position, auf die durch den Parameter pWaveOutIdverwiesen wird. Der Aufrufer kann diese ID verwenden, um das Waveform-Ausgabegerät zu öffnen, das über die angegebene Geräterolle verfügt.

Windows Vista unterstützt die DRV_QUERYFUNCTIONINSTANCEIDSIZE- und DRV_QUERYFUNCTIONINSTANCEID-Nachrichten. Sie werden in früheren Versionen von Windows, einschließlich Windows Server 2003, Windows XP und Windows 2000, nicht unterstützt.

Die Funktion im vorherigen Codebeispiel ruft die Waveform-Geräte-ID für ein Renderinggerät ab, kann jedoch mit einigen Änderungen angepasst werden, um die Waveform-Geräte-ID für ein Aufnahmegerät abzurufen. Die Anwendung kann dann waveInOpen mit dieser ID aufrufen, um das Gerät zu öffnen. Gehen Sie wie folgt vor, um die Waveform-Geräte-ID für das Audioaufnahme-Endpunktgerät abzurufen, das einer bestimmten Rolle zugewiesen ist:

  • Ersetzen Sie alle waveOutXxx- Funktionsaufrufe im vorherigen Beispiel durch die entsprechenden waveInXxx Funktionsaufrufe.
  • Änderungsziehpunkttyp HWAVEOUT in HWAVEIN.
  • Ersetzen Sie ERole Enumerationskonstante eRender durch eCapture.

In Windows Vista weisen die funktionen waveOutOpen und waveInOpen immer die Audiodatenströme zu, die sie der Standardsitzung erstellen – der prozessspezifischen Sitzung, die durch den Sitzungs-GUID-Wert GUID_NULL identifiziert wird.

Interoperabilität mit älteren Audio-APIs