Partilhar via


Propriedade de Descrição Jack

No Windows Vista e versões posteriores, a propriedade KSPROPERTY_JACK_DESCRIPTION descreve uma tomada de áudio ou outro conector físico em um adaptador de áudio. O valor da propriedade descreve a cor da tomada, a localização física da tomada, o tipo de conector e outros recursos da tomada. O objetivo dessas informações é ajudar o usuário a encontrar a tomada correta para conectar um dispositivo de ponto final de áudio, como um microfone, fones de ouvido ou alto-falantes. Para obter mais informações, consulte Audio Endpoint Devices.

Se um filtro KS em um adaptador de áudio suportar a propriedade KSPROPERTY_JACK_DESCRIPTION, o painel de controle multimídia do Windows, Mmsys.cpl, exibirá as informações do conector para os pinos de ponte no filtro. Um pino de ponte representa uma conexão (normalmente, um jack) com um dispositivo de ponto de extremidade de áudio. Embora o valor da propriedade contenha informações sobre um conector (ou, mais especificamente, o conector ou conectores associados), a propriedade é uma característica do filtro, não do conector. Para obter mais informações sobre pinos de ponte, consulte Gráficos de filtro de áudio. Para obter mais informações sobre propriedades de filtro e propriedades de pino, consulte Propriedades de filtro, pino e nó.

Um aplicativo de áudio pode obter o valor da propriedade KSPROPERTY_JACK_DESCRIPTION para um dispositivo de ponto de extremidade de áudio chamando o método IKsJackDescription::GetJackDescription na API DeviceTopology. Por exemplo, um aplicativo pode usar as informações do conector para ajudar o usuário a distinguir um microfone conectado a um conector XLR verde de um microfone conectado a um conector XLR laranja. Para obter mais informações sobre a API DeviceTopology, consulte Topologias de dispositivo.

O driver de classe Microsoft HD Audio constrói de forma automática os valores da propriedade KSPROPERTY_JACK_DESCRIPTION a partir dos dados que lê dos registos de configuração de pinos num codec Áudio HD. No entanto, qualquer driver de áudio baseado em KS pode implementar suporte para essa propriedade em suas tabelas de automação de filtro. Para obter mais informações sobre o driver de classe HD Audio, consulte HD Audio e UAA. Para obter mais informações sobre registradores de configuração de pinos, consulte o white paper Diretrizes de configuração de pinos para dispositivos de áudio de alta definição .

Um dispositivo de ponto final de áudio pode ligar-se a um pino de interligação através de uma ou mais jacks. Por exemplo, um conjunto de alto-falantes estéreo (dois canais) requer um jack, mas um conjunto de alto-falantes de som surround 5.1 requer três jacks (assumindo que cada jack lida com dois dos seis canais).

A descrição de cada jack está contida numa estrutura KSJACK_DESCRIPTION. Por exemplo, o valor da propriedade KSPROPERTY_JACK_DESCRIPTION para um dispositivo de ponto de extremidade de áudio com um conector contém uma estrutura KSJACK_DESCRIPTION, mas o valor da propriedade para um dispositivo de ponto de extremidade com três conectores contém três estruturas KSJACK_DESCRIPTION. Em ambos os casos, a estrutura ou estruturas KSJACK_DESCRIPTION no valor da propriedade são precedidas por uma estrutura KSMULTIPLE_ITEM que especifica o tamanho do valor da propriedade. Para obter mais informações, consulte KSPROPERTY_JACK_DESCRIPTION.

As informações de Jack são particularmente úteis para ajudar os usuários a distinguir entre as tomadas que se conectam a uma configuração de alto-falante multicanal. O exemplo de código a seguir mostra uma matriz de estruturas de KSJACK_DESCRIPTION que um driver de áudio usa para descrever os três conectores para um conjunto de alto-falantes surround 5.1:

KSJACK_DESCRIPTION ar_5dot1_Jacks[] =
{
    // Jack 1
    {
        (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT), // ChannelMapping (L,R)
        RGB(0,255,0),       // Color (green)
        eConnType3Point5mm, // ConnectionType
        eGeoLocRear,        // GeoLocation
        eGenLocPrimaryBox,  // GenLocation
        ePortConnJack,      // PortConnection
        TRUE                // IsConnected
    },
    // Jack 2
    {
        (SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY), // (C,Sub)
        RGB(0,0,255),       // (red)
        eConnType3Point5mm,
        eGeoLocRear,
        eGenLocPrimaryBox,
        ePortConnJack,
        TRUE
    },
    // Jack 3
    {
        (SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT),  // (SL,SR)
        RGB(0,255,255),     // (yellow)
        eConnType3Point5mm,
        eGeoLocRear,
        eGenLocPrimaryBox,
        ePortConnJack,
        TRUE
    }
};

Se o hardware de áudio puder detetar se o dispositivo está conectado, o driver atualiza dinamicamente o valor desse membro para indicar se o dispositivo está conectado (TRUE) ou desconectado (FALSE)

No exemplo de código anterior, o membro IsConnected em cada elemento de matriz é definido como TRUE para indicar que o dispositivo de ponto de extremidade está conectado à tomada. No entanto, se o hardware não tiver deteção de presença de jack, IsConnected deve sempre ser definido como TRUE, se houver um dispositivo conectado à tomada. Para remover a ambiguidade que resulta desse significado duplo do valor de retorno TRUE , um aplicativo cliente pode chamar IKsJackDescription2::GetJackDescription2 para ler o sinalizador JackCapabilities da estrutura KSJACK_DESCRIPTION2 . Se esse sinalizador tiver o JACKDESC2_PRESENCE_DETECT_CAPABILITY bit definido, isso indica que o ponto de extremidade de fato suporta a deteção de presença de jack. Nesse caso, o valor do membro IsConnected pode ser interpretado como um reflexo preciso do estado de inserção do jack.

A macro RGB que aparece nas estruturas anteriores é definida no arquivo de cabeçalho Wingdi.h no SDK do Windows.

Além disso, uma matriz de descrições de jack pode ser usada para mostrar que dois ou mais jacks são funcionalmente equivalentes entre si. No exemplo de código a seguir, o driver de áudio combina as descrições de tomada para um conector RCA amarelo e para um conector digital-óptico preto em uma matriz para indicar ao usuário que os dois conectores carregam o mesmo sinal:

KSJACK_DESCRIPTION ar_SPDIF_Jacks[] =
{
    // Jack 1
    {
        (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT), // ChannelMapping (L,R)
        RGB(0,255,255),         // Color (yellow)
        eConnTypeRCA,           // ConnectionType (RCA)
        eGeoLocRear,            // GeoLocation
 eGenLocPrimaryBox,   // GenLocation
        ePortConnJack,       // PortConnection
        TRUE                    // IsConnected
    },
    // Jack 2
    {
        (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT), // (L,R)
        RGB(0,0,0),             // (black)
        eConnTypeOptical,       // (optical)
        eGeoLocRear,
 eGenLocPrimaryBox,
        ePortConnJack,
        TRUE
    }
};

No exemplo de código anterior, os valores dos membros ChannelMapping nas duas estruturas KSJACK_DESCRIPTION são idênticos.

O driver de exemplo MSVAD "Simples" no WDK (no diretório de exemplo Src\Audio\Msvad\Simple) pode ser adaptado para suportar a propriedade KSPROPERTY_JACK_DESCRIPTION. Este driver de exemplo é conveniente para demonstrar o uso da propriedade porque não requer hardware real. Assim, pode ser instalado em qualquer computador com Windows. (No entanto, apenas o Windows Vista e sistemas operacionais posteriores fornecem suporte total para a propriedade KSPROPERTY_JACK_DESCRIPTION.) Para obter mais informações sobre este exemplo, consulte Exemplos de Kit de Driver do Windows.

O filtro de topologia para o exemplo de MSVAD simples define três pinos de ponte. Esses pinos estão listados na tabela a seguir.

ID do pino Descrição

KSPIN_TOPO_SYNTHIN_SOURCE

Tomada de entrada MIDI

KSPIN_TOPO_MIC_SOURCE

Tomada de entrada para microfone

KSPIN_TOPO_LINEOUT_DEST

Tomada de saída de altifalante estéreo

O restante deste tópico explica como modificar o driver de exemplo MSVAD simples para fornecer as informações de tomada para os três pinos de ponte.

Primeiro, as informações do conector para esses pinos podem ser especificadas da seguinte maneira:

// Describe MIDI input jack (pin ID = KSPIN_TOPO_SYNTHIN_SOURCE).
static KSJACK_DESCRIPTION SynthIn_Jack[] =
{
    {
        0,                  // ChannelMapping
        RGB(255,255,0),    // Color (cyan)
 eConnType3Point5mm, // ConnectionType
        eGeoLocRear,        // GeoLocation
        eGenLocPrimaryBox,  // GenLocation
        ePortConnJack,      // PortConnection
        TRUE                // IsConnected
    }
};

// Describe microphone jack (pin ID = KSPIN_TOPO_MIC_SOURCE).
static KSJACK_DESCRIPTION MicIn_Jack[] =
{
    {
        0,
        RGB(0,128,255),   // (orange)
 eConnType3Point5mm,
        eGeoLocFront,
        eGenLocPrimaryBox,
        ePortConnJack,
        TRUE
    }
};

// Describe stereo speaker jack (pin ID = KSPIN_TOPO_LINEOUT_DEST).
static KSJACK_DESCRIPTION LineOut_Jack[] =
{
    {
        (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT), // ChannelMapping (L,R)
        RGB(0,255,0),       // (green)
 eConnType3Point5mm,
        eGeoLocRear,
        eGenLocPrimaryBox,
        ePortConnJack,
        TRUE
    }
};

O exemplo de código anterior define os membros ChannelMapping para os dois pinos de captura como 0. Somente pinos de renderização analógicos devem ter valores ChannelMapping diferentes de zero.

A modificação principal no exemplo Simple MSVAD é adicionar o seguinte manipulador de propriedade à implementação da miniporta de topologia no arquivo de exemplo Mintopo.cpp.

#define ARRAY_LEN(a)  sizeof(a)/sizeof(a[0]);
#define MAXIMUM_VALID_PIN_ID  KSPIN_TOPO_WAVEIN_DEST

NTSTATUS
CMiniportTopology::PropertyHandlerJackDescription(
               IN PPCPROPERTY_REQUEST PropertyRequest)
{
    PAGED_CODE();

    ASSERT(PropertyRequest);

    DPF_ENTER(("[PropertyHandlerJackDescription]"));

    NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    ULONG nPinId = (ULONG)-1;

    if (PropertyRequest->InstanceSize >= sizeof(ULONG))
    {
        nPinId = *((PULONG)(PropertyRequest->Instance));

        if (nPinId > MAXIMUM_VALID_PIN_ID)
        {
            ntStatus = STATUS_INVALID_PARAMETER;
        }
        else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
        {
            ntStatus = PropertyHandler_BasicSupport(
                            PropertyRequest,
                            KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
                            VT_ILLEGAL);
        }
        else
        {
            PKSJACK_DESCRIPTION pJack = NULL;
            ULONG cJacks = 0;

            switch (nPinId)
            {
            case KSPIN_TOPO_SYNTHIN_SOURCE:
                pJack = SynthIn_Jack;
                cJacks = ARRAY_LEN(SynthIn_Jack);
                break;
            case KSPIN_TOPO_MIC_SOURCE:
                pJack = MicIn_Jack;
                cJacks = ARRAY_LEN(MicIn_Jack);
                break;
            case KSPIN_TOPO_LINEOUT_DEST:
                pJack = LineOut_Jack;
                cJacks = ARRAY_LEN(LineOut_Jack);
                break;
            default:
                break;
            }

            ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) +
                             sizeof(KSJACK_DESCRIPTION) * cJacks;

            if (PropertyRequest->ValueSize == 0)
            {
                PropertyRequest->ValueSize = cbNeeded;
                ntStatus = STATUS_BUFFER_OVERFLOW;
            }
            else if (PropertyRequest->ValueSize < cbNeeded)
            {
                ntStatus = STATUS_BUFFER_TOO_SMALL;
            }
            else if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
            {
                PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;

                pMI->Size = cbNeeded;
                pMI->Count = cJacks;

                // Copy jack description structure into Value buffer.
                // RtlCopyMemory correctly handles the case Length=0.
                PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI + 1);

                RtlCopyMemory(pDesc, pJack, pMI->Size * pMI->Count);

                ntStatus = STATUS_SUCCESS;
            }
        }
    }

    return ntStatus;
}

NTSTATUS
PropertyHandler_TopoFilter(IN PPCPROPERTY_REQUEST PropertyRequest)
{
    PAGED_CODE();

    ASSERT(PropertyRequest);

    DPF_ENTER(("[PropertyHandler_TopoFilter]"));

    // PropertyRequest structure is filled by PortCls.
    // MajorTarget is a pointer to miniport object for miniports.
    //
    NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;

    if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack) &&
        (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION))
    {
        ntStatus = pMiniport->PropertyHandlerJackDescription(PropertyRequest);
    }

    return ntStatus;
}

O exemplo de código anterior refere-se às três variáveis KSJACK_DESCRIPTION - SynthIn_Jack, MicIn_Jack e LineOut_Jack - que foram definidas anteriormente. Se o cliente consultar o filtro para obter a descrição do jack de um pino válido, mas que não seja um pino de ponte (e, portanto, não tenha descrição de jack), a consulta terá êxito (com código de status STATUS_SUCCESS), mas o manipulador de propriedades retorna uma descrição de jack vazia composta apenas por uma estrutura KSMULTIPLE_ITEM. Se o cliente especificar um ID de pino inválido (que identifique um pino inexistente), o manipulador retornará o código de status STATUS_INVALID_PARAMETER.

Duas modificações adicionais para o exemplo de MSVAD simples são necessárias para dar suporte à propriedade KSPROPERTY_JACK_DESCRIPTION. São eles:

  • Adicione a declaração do método PropertyHandlerJackDescription no exemplo de código anterior à definição de classe CMiniportTopology no arquivo de cabeçalho Mintopo.h.

  • Implemente uma tabela de automação para o filtro de topologia e carregue o endereço dessa tabela no membro AutomationTable da estrutura PCFILTER_DESCRIPTOR no ficheiro de cabeçalho Toptable.h. Essa estrutura é chamada MiniportFilterDescriptor.

Para implementar a tabela de automação para o filtro, insira o seguinte código no arquivo de cabeçalho Toptable.h (antes da definição de MiniportFilterDescriptor):

static PCPROPERTY_ITEM PropertiesTopoFilter[] =
{
    {
        &KSPROPSETID_Jack,
        KSPROPERTY_JACK_DESCRIPTION,
        KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
        PropertyHandler_TopoFilter
    }
};

DEFINE_PCAUTOMATION_TABLE_PROP(AutomationTopoFilter, PropertiesTopoFilter);

No exemplo de código anterior, o membro Handler da estrutura PCPROPERTY_ITEM contém um ponteiro de função para o manipulador de propriedades que foi adicionado a Mintopo.cpp em uma etapa anterior. Para tornar o manipulador de propriedades acessível a partir do arquivo de cabeçalho, insira uma declaração de função externa para PropertyHandler_TopoFilter no início do arquivo de cabeçalho.

Para obter mais informações sobre a propriedade de descrição do jack, consulte Jack Descriptions for Dynamic Audio Subdevices.