Share via


Rôles d’appareil pour les applications multimédias Windows héritées

Notes

L’API MMDevice prend en charge les rôles d’appareil. Toutefois, l’interface utilisateur dans Windows Vista n’implémente pas la prise en charge de cette fonctionnalité. La prise en charge de l’interface utilisateur pour les rôles d’appareil peut être implémentée dans une version ultérieure de Windows. Pour plus d’informations, consultez Rôles d’appareil dans Windows Vista.

 

Les fonctions multimédias waveOutXxx et waveInXxx windows héritées ne fournissent aucun moyen pour une application de sélectionner l’appareil de point de terminaison audio que l’utilisateur a attribué à un rôle d’appareil particulier. Toutefois, dans Windows Vista, les API audio principales peuvent être utilisées conjointement avec une application multimédia Windows pour permettre la sélection d’appareils en fonction du rôle d’appareil. Par exemple, à l’aide de l’API MMDevice, une application waveOutXxx peut identifier l’appareil de point de terminaison audio affecté à un rôle, identifier l’appareil de sortie de forme d’onde correspondant et appeler la fonction waveOutOpen pour ouvrir un instance de l’appareil. Pour plus d’informations sur waveOutXxx et waveInXxx, consultez la documentation du Kit de développement logiciel (SDK) Windows.

L’exemple de code suivant montre comment obtenir l’ID d’appareil waveform pour l’appareil de point de terminaison de rendu affecté à un rôle d’appareil particulier :

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

Dans l’exemple de code précédent, la fonction GetWaveOutId accepte un rôle d’appareil (eConsole, eMultimedia ou eCommunications) en tant que paramètre d’entrée. Le deuxième paramètre est un pointeur par lequel la fonction écrit l’ID d’appareil de forme d’onde pour l’appareil de sortie de forme d’onde affecté au rôle spécifié. L’application peut ensuite appeler waveOutOpen avec cet ID pour ouvrir l’appareil.

La boucle main dans l’exemple de code précédent contient deux appels à la fonction waveOutMessage. Le premier appel envoie un message DRV_QUERYFUNCTIONINSTANCEIDSIZE pour récupérer la taille, en octets, de la chaîne d’ID de point de terminaison de l’appareil de forme d’onde identifiée par le paramètre waveOutId . (La chaîne d’ID de point de terminaison identifie l’appareil de point de terminaison audio qui sous-tend l’abstraction de l’appareil de forme d’onde.) La taille signalée par cet appel inclut l’espace pour le caractère null de fin à la fin de la chaîne. Le programme peut utiliser les informations de taille pour allouer une mémoire tampon suffisamment grande pour contenir l’ensemble de la chaîne d’ID de point de terminaison.

Le deuxième appel à waveOutMessage envoie un message DRV_QUERYFUNCTIONINSTANCEID pour récupérer la chaîne d’ID d’appareil de l’appareil de sortie de forme d’onde. L’exemple de code compare cette chaîne à la chaîne d’ID d’appareil du périphérique de point de terminaison audio avec le rôle d’appareil spécifié. Si les chaînes correspondent, la fonction écrit l’ID d’appareil de forme d’onde dans l’emplacement pointé par le paramètre pWaveOutId. L’appelant peut utiliser cet ID pour ouvrir l’appareil de sortie de forme d’onde qui a le rôle d’appareil spécifié.

Windows Vista prend en charge les messages DRV_QUERYFUNCTIONINSTANCEIDSIZE et DRV_QUERYFUNCTIONINSTANCEID. Ils ne sont pas pris en charge dans les versions antérieures de Windows, notamment Windows Server 2003, Windows XP et Windows 2000.

La fonction de l’exemple de code précédent obtient l’ID d’appareil de forme d’onde pour un appareil de rendu, mais, avec quelques modifications, elle peut être adaptée pour obtenir l’ID d’appareil de forme d’onde pour un appareil de capture. L’application peut ensuite appeler waveInOpen avec cet ID pour ouvrir l’appareil. Pour modifier l’exemple de code précédent afin d’obtenir l’ID d’appareil de forme d’onde pour l’appareil de point de terminaison de capture audio affecté à un rôle particulier, procédez comme suit :

  • Remplacez tous les appels de fonction waveOutXxx dans l’exemple précédent par les appels de fonction waveInXxx correspondants.
  • Remplacez le type de handle HWAVEOUT par HWAVEIN.
  • Remplacez la constante d’énumération ERole eRender par eCapture.

Dans Windows Vista, les fonctions waveOutOpen et waveInOpen attribuent toujours les flux audio qu’elles créent à la session par défaut, la session spécifique au processus identifiée par la valeur GUID de session GUID_NULL.

Interopérabilité avec les API audio héritées