Dela via


Enhetsroller för äldre Windows Multimedia-program

Not

MMDevice-API:et stöder enhetsroller. Användargränssnittet i Windows Vista implementerar dock inte stöd för den här funktionen. Användargränssnittsstöd för enhetsroller kan implementeras i en framtida version av Windows. Mer information finns i Enhetsroller i Windows Vista.

 

De äldre funktionerna i Windows multimedia waveOutXxx och waveInXxx ger inget sätt för ett program att välja den ljudslutpunktsenhet som användaren har tilldelat till en viss enhetsroll. I Windows Vista kan dock kärnljud-API:er användas tillsammans med ett Multimedieprogram i Windows för att aktivera enhetsval baserat på enhetsroll. Med hjälp av MMDevice APIkan till exempel ett waveOutXxx--program identifiera den ljudslutpunktsenhet som har tilldelats en roll, identifiera motsvarande utdataenhet för vågform och anropa funktionen waveOutOpen för att öppna en instans av enheten. Mer information om waveOutXxx och waveInXxxfinns i Windows SDK-dokumentationen.

I följande kodexempel visas hur du hämtar waveform-enhets-ID:t för den återgivningsslutpunktsenhet som har tilldelats en viss enhetsroll:

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

I föregående kodexempel accepterar funktionen GetWaveOutId en enhetsroll (eConsole, eMultimedia eller eCommunications) som en indataparameter. Den andra parametern är en pekare genom vilken funktionen skriver vågformens enhets-ID för den vågformsutdataenhet som har tilldelats den angivna rollen. Programmet kan sedan anropa waveOutOpen med det här ID:t för att öppna enheten.

Huvudslingan i föregående kodexempel innehåller två anrop till funktionen waveOutMessage. Det första anropet skickar ett DRV_QUERYFUNCTIONINSTANCEIDSIZE meddelande för att hämta storleken, i byte, på slutpunkts-ID-strängen för vågformsenheten som identifieras av parametern waveOutId. (Slutpunkts-ID-strängen identifierar ljudslutpunktsenheten som ligger till grund för vågformens enhetsabstraktion.) Storleken som rapporteras av det här anropet innehåller utrymmet för det avslutande null-tecknet i slutet av strängen. Programmet kan använda storleksinformationen för att allokera en buffert som är tillräckligt stor för att innehålla hela slutpunkts-ID-strängen.

Det andra anropet till waveOutMessage skickar ett DRV_QUERYFUNCTIONINSTANCEID meddelande för att hämta enhets-ID-strängen för waveform-utdataenheten. Exempelkoden jämför den här strängen med enhets-ID-strängen för ljudslutpunktsenheten med den angivna enhetsrollen. Om strängarna matchar skriver funktionen vågformens enhets-ID till den plats som pekas på av parametern pWaveOutId. Anroparen kan använda det här ID:t för att öppna den vågformsutdataenhet som har den angivna enhetsrollen.

Windows Vista stöder DRV_QUERYFUNCTIONINSTANCEIDSIZE- och DRV_QUERYFUNCTIONINSTANCEID-meddelanden. De stöds inte i tidigare versioner av Windows, inklusive Windows Server 2003, Windows XP och Windows 2000.

Funktionen i föregående kodexempel hämtar vågformens enhets-ID för en återgivningsenhet, men med några ändringar kan den anpassas för att hämta vågformens enhets-ID för en avbildningsenhet. Programmet kan sedan anropa waveInOpen med det här ID:t för att öppna enheten. Om du vill ändra föregående kodexempel för att hämta waveform-enhets-ID för slutpunktsenheten för ljudupptagning som har tilldelats en viss roll gör du följande:

  • Ersätt alla waveOutXxx funktionsanrop i föregående exempel med motsvarande waveInXxx funktionsanrop.
  • Ändra referenstypen HWAVEOUT till HWAVEIN.
  • Ersätt ERole uppräkningskonstanten eRender med eCapture.

I Windows Vista tilldelar waveOutOpen och waveInOpen funktioner alltid de ljudströmmar som de skapar till standardsessionen – den processspecifika session som identifieras av sessionens GUID-värde GUID_NULL.

samverkan med äldre ljud-API:er