Utilisation de l’interface IKsControl pour accéder aux propriétés audio

Dans de rares cas, une application audio spécialisée peut avoir besoin d’utiliser l’interface IKsControl pour accéder à certaines fonctionnalités matérielles d’une carte audio qui ne sont pas exposées par l’API DeviceTopology ou l’API MMDevice. L’interface IKsControl rend les propriétés, les événements et les méthodes des appareils de diffusion en continu de noyau (KS) disponibles pour les applications en mode utilisateur. Les propriétés KS présentent un intérêt principal pour les applications audio. L’interface IKsControl peut être utilisée conjointement avec l’API DeviceTopology et l’API MMDevice pour accéder aux propriétés KS des cartes audio.

L’interface IKsControl est principalement destinée aux fournisseurs de matériel qui écrivent des applications de panneau de configuration pour gérer leur matériel audio. IKsControl est moins utile pour les applications audio à usage général qui ne sont pas liées à des périphériques matériels particuliers. La raison en est que les fournisseurs de matériel implémentent fréquemment des mécanismes propriétaires pour accéder aux propriétés audio de leurs appareils. Contrairement à l’API DeviceTopology, qui masque les bizarreries des pilotes spécifiques au matériel et fournit une interface relativement uniforme pour accéder aux propriétés audio, les applications utilisent IKsControl pour communiquer directement avec les pilotes. Pour plus d’informations sur IKsControl, consultez la documentation windows DDK.

Comme indiqué dans Topologies d’appareil, une sous-unité dans la topologie d’un périphérique adaptateur peut prendre en charge une ou plusieurs interfaces de contrôle spécifiques à la fonction indiquées dans la colonne de gauche du tableau suivant. Chaque entrée de la colonne de droite de la table est la propriété KS qui correspond à l’interface de contrôle à gauche. L’interface de contrôle fournit un accès pratique à la propriété. La plupart des pilotes audio utilisent des propriétés KS pour représenter les fonctionnalités de traitement spécifiques aux fonctions des sous-unités (également appelées nœuds KS) dans les topologies de leurs cartes audio. Pour plus d’informations sur les propriétés KS et les nœuds KS, consultez la documentation windows DDK.

Interface de contrôle KS, propriété
IAudioAutoGainControl KSPROPERTY_AUDIO_AGC
IAudioBass KSPROPERTY_AUDIO_BASS
IAudioChannelConfig KSPROPERTY_AUDIO_CHANNEL_CONFIG
IAudioInputSelector KSPROPERTY_AUDIO_MUX_SOURCE
IAudioLoudness KSPROPERTY_AUDIO_LOUDNESS
IAudioMidrange KSPROPERTY_AUDIO_MID
IAudioMute KSPROPERTY_AUDIO_MUTE
IAudioOutputSelector KSPROPERTY_AUDIO_DEMUX_DEST
IAudioPeakMeter KSPROPERTY_AUDIO_PEAKMETER
IAudioTreble KSPROPERTY_AUDIO_TREBLE
IAudioVolumeLevel KSPROPERTY_AUDIO_VOLUMELEVEL
IDeviceSpecificProperty KSPROPERTY_AUDIO_DEV_SPECIFIC

 

Les topologies de certaines cartes audio peuvent contenir des sous-unités qui ont des propriétés KS qui ne sont pas répertoriées dans le tableau précédent. Par exemple, supposons qu’un appel à la méthode IPart::GetSubType pour une sous-unité particulière récupère la valeur GUID KSNODETYPE_TONE. Ce GUID de sous-type indique que la sous-unité prend en charge une ou plusieurs des propriétés KS suivantes :

  • KSPROPERTY_AUDIO_BASS
  • KSPROPERTY_AUDIO_MID
  • KSPROPERTY_AUDIO_TREBLE
  • KSPROPERTY_AUDIO_BASS_BOOST

Les trois premières propriétés de cette liste sont accessibles via les interfaces de contrôle qui apparaissent dans le tableau précédent, mais la propriété KSPROPERTY_AUDIO_BASS_BOOST n’a pas d’interface de contrôle correspondante dans l’API DeviceTopology. Toutefois, une application peut utiliser l’interface IKsControl pour accéder à cette propriété, si la sous-unité prend en charge la propriété .

Les étapes suivantes sont requises pour accéder à la propriété KSPROPERTY_AUDIO_BASS_BOOST d’une sous-unité de sous-type KSNODETYPE_TONE :

  1. Appelez la méthode IConnector::GetDeviceIdConnectedTo ou IDeviceTopology::GetDeviceId pour obtenir la chaîne d’ID d’appareil qui identifie l’appareil adaptateur. Cette chaîne est similaire à une chaîne d’ID de point de terminaison, sauf qu’elle identifie un périphérique adaptateur au lieu d’un appareil de point de terminaison. Pour plus d’informations sur la différence entre un périphérique adaptateur et un appareil de point de terminaison, consultez Appareils de point de terminaison audio.
  2. Obtenez l’interface IMMDevice de l’appareil adaptateur en appelant la méthode IMMDeviceEnumerator::GetDevice avec la chaîne d’ID d’appareil. Cette interface IMMDevice est identique à l’interface décrite dans IMMDevice Interface, mais elle représente un périphérique adaptateur au lieu d’un périphérique de point de terminaison.
  3. Obtenez l’interface IKsControl sur la sous-unité en appelant la méthode IMMDevice::Activate avec le paramètre iid défini sur REFIID IID_IKsControl. Notez que les interfaces prises en charge par cette méthode Activate , qui concerne un périphérique adaptateur, sont différentes des interfaces prises en charge par la méthode Activate pour un appareil de point de terminaison. En particulier, la méthode Activate pour un périphérique d’adaptateur prend en charge IKsControl.
  4. Appelez la méthode IPart::GetLocalId pour obtenir l’ID local de la sous-unité.
  5. Créez une demande de propriété KS. L’ID de nœud KS requis pour la requête est contenu dans les 16 bits les moins significatifs de l’ID local obtenu à l’étape précédente.
  6. Envoyez la demande de propriété KS au pilote audio en appelant la méthode IKsControl::KsProperty . Pour plus d’informations sur cette méthode, consultez la documentation windows DDK.

L’exemple de code suivant récupère la valeur de la propriété KSPROPERTY_AUDIO_BASS_BOOST à partir d’une sous-unité de sous-type KSNODETYPE_TONE :

//-----------------------------------------------------------
// This function calls the IKsControl::Property method to get
// the value of the KSPROPERTY_AUDIO_BASS_BOOST property of
// a subunit. Parameter pPart should point to a part that is
// a subunit with a subtype GUID value of KSNODETYPE_TONE.
//-----------------------------------------------------------
#define PARTID_MASK 0x0000ffff
#define EXIT_ON_ERROR(hres)  \
              if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

const IID IID_IKsControl = __uuidof(IKsControl);

HRESULT GetBassBoost(IMMDeviceEnumerator *pEnumerator,
                     IPart *pPart, BOOL *pbValue)
{
    HRESULT hr;
    IDeviceTopology *pTopology = NULL;
    IMMDevice *pPnpDevice = NULL;
    IKsControl *pKsControl = NULL;
    LPWSTR pwszDeviceId = NULL;

    if (pEnumerator == NULL || pPart == NULL || pbValue == NULL)
    {
        return E_INVALIDARG;
    }

    // Get the topology object for the adapter device that contains
    // the subunit represented by the IPart interface.
    hr = pPart->GetTopologyObject(&pTopology);
    EXIT_ON_ERROR(hr)

    // Get the device ID string that identifies the adapter device.
    hr = pTopology->GetDeviceId(&pwszDeviceId);
    EXIT_ON_ERROR(hr)

    // Get the IMMDevice interface of the adapter device object.
    hr = pEnumerator->GetDevice(pwszDeviceId, &pPnpDevice);
    EXIT_ON_ERROR(hr)

    // Activate an IKsControl interface on the adapter device object.
    hr = pPnpDevice->Activate(IID_IKsControl, CLSCTX_ALL, NULL, (void**)&pKsControl);
    EXIT_ON_ERROR(hr)

    // Get the local ID of the subunit (contains the KS node ID).
    UINT localId = 0;
    hr = pPart->GetLocalId(&localId);
    EXIT_ON_ERROR(hr)

    KSNODEPROPERTY_AUDIO_CHANNEL ksprop;
    ZeroMemory(&ksprop, sizeof(ksprop));
    ksprop.NodeProperty.Property.Set = KSPROPSETID_Audio;
    ksprop.NodeProperty.Property.Id = KSPROPERTY_AUDIO_BASS_BOOST;
    ksprop.NodeProperty.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
    ksprop.NodeProperty.NodeId = localId & PARTID_MASK;
    ksprop.Channel = 0;

    // Send the property request.to the device driver.
    BOOL bValue = FALSE;
    ULONG valueSize;
    hr = pKsControl->KsProperty(
                         &ksprop.NodeProperty.Property, sizeof(ksprop),
                         &bValue, sizeof(bValue), &valueSize);
    EXIT_ON_ERROR(hr)

    *pbValue = bValue;

Exit:
    SAFE_RELEASE(pTopology)
    SAFE_RELEASE(pPnpDevice)
    SAFE_RELEASE(pKsControl)
    CoTaskMemFree(pwszDeviceId);
    return hr;
}

Dans l’exemple de code précédent, la fonction GetBassBoost prend les trois paramètres suivants :

  • pEnumerator pointe vers l’interface IMMDeviceEnumerator d’un énumérateur de point de terminaison audio.
  • pPart pointe vers l’interface IPart d’une sous-unité qui a un sous-type de KSNODETYPE_TONE.
  • pbValue pointe vers une variable BOOL dans laquelle la fonction écrit la valeur de propriété.

Un programme appelle GetBassBoost uniquement après avoir appelé IPart::GetSubType et détermine que le sous-type de la sous-unité est KSNODETYPE_TONE. La valeur de la propriété est TRUE si l’augmentation des basses est activée. Il est FALSE si l’augmentation des basses est désactivée.

Au début de la fonction GetBassBoost, l’appel à la méthode IPart::GetTopologyObject obtient l’interface IDeviceTopology de l’appareil adaptateur qui contient la sous-unité KSNODETYPE_TONE. L’appel de méthode IDeviceTopology::GetDeviceId récupère la chaîne d’ID d’appareil qui identifie l’appareil adaptateur. L’appel de méthode IMMDeviceEnumerator::GetDevice prend la chaîne d’ID d’appareil comme paramètre d’entrée et récupère l’interface IMMDevice de l’appareil adaptateur. Ensuite, l’appel de méthode IMMDevice::Activate récupère l’interface IKsControl de la sous-unité. Pour plus d’informations sur l’interface IKsControl , consultez la documentation windows DDK.

Ensuite, l’exemple de code précédent crée une structure KSNODEPROPERTY_AUDIO_CHANNEL qui décrit la propriété bass-boost. L’exemple de code transmet un pointeur vers la structure vers la méthode IKsControl::KsProperty , qui utilise les informations de la structure pour récupérer la valeur de la propriété. Pour plus d’informations sur la structure KSNODEPROPERTY_AUDIO_CHANNEL et la méthode IKsControl::KsProperty , consultez la documentation du DDK Windows.

Le matériel audio attribue généralement un état de renforcement des basses distinct à chaque canal d’un flux audio. En principe, la stimulation des basses peut être activée pour certains canaux et désactivée pour d’autres. La structure KSNODEPROPERTY_AUDIO_CHANNEL contient un membre channel qui spécifie le numéro de canal. Si un flux contient N canaux, les canaux sont numérotés de 0 à N— 1. L’exemple de code précédent obtient la valeur de la propriété bass-boost pour le canal 0 uniquement. Cette implémentation suppose implicitement que les propriétés bass-boost de tous les canaux sont définies uniformément au même état. Par conséquent, la lecture de la propriété bass-boost pour le canal 0 est suffisante pour déterminer la valeur de la propriété bass-boost pour le flux. Pour être cohérent avec cette hypothèse, une fonction correspondante pour définir la propriété bass-boost affecterait à tous les canaux la même valeur de propriété bass-boost. Il s’agit de conventions raisonnables, mais tous les fournisseurs de matériel ne les suivent pas nécessairement. Par exemple, un fournisseur peut fournir une application de panneau de configuration qui active l’amplification des basses uniquement pour les canaux qui pilotent des haut-parleurs de gamme complète. (Un haut-parleur de gamme complète est capable de lire des sons sur toute la plage, des basses aux aigus.) Dans ce cas, la valeur de propriété récupérée par l’exemple de code précédent peut ne pas représenter avec précision l’état bass-boost du flux.

Les clients qui utilisent les interfaces de contrôle répertoriées dans le tableau précédent peuvent appeler la méthode IPart::RegisterControlChangeCallback pour s’inscrire aux notifications lorsque la valeur d’un paramètre de contrôle change. Notez que l’interface IKsControl ne fournit pas un moyen similaire pour les clients de s’inscrire aux notifications lorsqu’une valeur de propriété change. Si IKsControl prend en charge les notifications de modification de propriété, il peut informer une application lorsqu’une autre application a modifié une valeur de propriété. Toutefois, contrairement aux contrôles plus couramment utilisés qui sont surveillés par le biais de notifications IPart , les propriétés gérées par IKsControl sont principalement destinées aux fournisseurs de matériel, et ces propriétés sont susceptibles d’être modifiées uniquement par les applications de panneau de contrôle écrites par les fournisseurs. Si une application doit détecter les modifications apportées aux propriétés par une autre application, elle peut détecter les modifications en interrogeant régulièrement la valeur de la propriété via IKsControl.

Guide de programmation