Свойство Описания Джека

В Windows Vista и более поздних версиях свойство KSPROPERTY_JACK_DESCRIPTION описывает звуковой разъем или другой физический соединитель на звуковом адаптере. Значение свойства описывает цвет джека, физическое расположение джека, тип соединителя и другие функции джека. Цель этой информации — помочь пользователю найти правильный джек для подключения к устройству аудио конечной точки, например микрофона, наушников или динамиков. Дополнительные сведения см. в аудиоконечных устройствах.

Если фильтр KS на звуковом адаптере поддерживает свойство KSPROPERTY_JACK_DESCRIPTION, панель управления мультимедиа Windows Mmsys.cplотображает сведения о разъемах для контактных штырей фильтра. Штырь моста представляет собой соединение (как правило, джек) с аудиоустройством. Хотя значение свойства содержит сведения о контакте (или, скорее, разъёме или разъёмах, связанных с контактом), свойство является свойством фильтра, а не контакта. Дополнительные сведения о штифтах для бриджа см. в разделе «Аудиофильтровые графы». Дополнительные сведения о свойствах фильтра и свойствах контактов см. в разделе «Свойства фильтров, контактов и узлов».

Звуковое приложение может получить значение свойства KSPROPERTY_JACK_DESCRIPTION для устройства аудио конечной точки, вызвав метод IKsJackDescription::GetJackDescription в API DeviceTopology. Например, приложение может использовать сведения о джеке, чтобы помочь пользователю отличить микрофон, подключенный к зеленому разъему XLR от микрофона, подключенного к оранжевым разъему XLR. Дополнительные сведения об API DeviceTopology см. в разделе " Топологии устройств".

Драйвер класса Microsoft HD Audio автоматически создает значения свойств KSPROPERTY_JACK_DESCRIPTION из данных, считываемых из регистров конфигурации контактов в кодеке HD Audio. Однако любой звуковой драйвер на основе KS может реализовать поддержку этого свойства в таблицах автоматизации фильтров. Дополнительные сведения о драйвере класса HD Audio см. в статье HD Audio и UAA. Дополнительные сведения о регистрах конфигурации пинов см. в руководстве по настройке пиновых конфигураций для устройств с высоким разрешением аудио.

Устройство конечной аудиоточки может подключаться к мосту через один или несколько разъемов. Например, для набора стереодинамиков (двухканальных) требуется один разъем, но для набора динамиков для объемного звука 5.1 требуется три разъема (при условии, что каждый разъем обрабатывает два из шести каналов).

Описание каждого джека содержится в структуре KSJACK_DESCRIPTION. Например, значение свойства KSPROPERTY_JACK_DESCRIPTION для устройства аудио конечной точки с одним джеком содержит одну KSJACK_DESCRIPTION структуру, но значение свойства для устройства конечной точки с тремя разъемами содержит три KSJACK_DESCRIPTION структуры. В любом случае структуре или структурам KSJACK_DESCRIPTION в значении свойства предшествует структура KSMULTIPLE_ITEM, указывающая размер значения свойства. Дополнительные сведения см. в KSPROPERTY_JACK_DESCRIPTION.

Сведения о разъёмах особенно полезны, чтобы помочь пользователям различать разъемы, подключающиеся к конфигурации многоканальных динамиков. В следующем примере кода показан массив структур KSJACK_DESCRIPTION, которые использует звуковой драйвер для описания трех разъемов для набора 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
    }
};

Если звуковое оборудование может определить, подключено ли устройство, драйвер динамически обновляет значение этого члена, чтобы указать, подключено ли устройство в данный момент (TRUE) или отключено (FALSE)

В приведенном выше примере кода элемент IsConnected в каждом элементе массива имеет значение TRUE , чтобы указать, что устройство конечной точки подключено к джеку. Тем не менее, если оборудование не имеет обнаружения присутствия джека, IsConnected всегда должно быть задано значение TRUE, независимо от того, подключено ли устройство к разъему. Чтобы устранить неоднозначность, возникающую из-за двойного значения возвращаемого значения TRUE, клиентское приложение может вызвать IKsJackDescription2::GetJackDescription2, чтобы прочитать флаг JackCapabilities структуры KSJACK_DESCRIPTION2. Если в этом флаге установлен бит JACKDESC2_PRESENCE_DETECT_CAPABILITY, это указывает, что устройство действительно поддерживает обнаружение подключения джека. В этом случае значение элемента IsConnected можно интерпретировать как точное отражение состояния вставки разъёма.

Макрос RGB, отображаемый в предыдущих структурах, определен в файле заголовка Wingdi.h в пакете SDK для Windows.

Кроме того, для демонстрации функциональной эквивалентности двух или более разъёмов можно использовать набор описаний разъёмов. В следующем примере кода звуковой драйвер объединяет описания джека для желтого джека RCA и для черного цифрового оптического джека в один массив, чтобы указать пользователю, что два джека несут один и тот же сигнал:

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

В предыдущем примере кода значения элементов ChannelMapping в двух KSJACK_DESCRIPTION структурах идентичны.

Образец драйвера "Simple" MSVAD в WDK (в каталоге примеров Src\Audio\Msvad\Simple) можно адаптировать для поддержки свойства KSPROPERTY_JACK_DESCRIPTION. Этот пример драйвера удобнее для демонстрации использования свойства, так как он не требует фактического оборудования. Таким образом, его можно установить на любом компьютере под управлением Windows. (Однако только операционные системы Windows Vista и более поздних версий обеспечивают полную поддержку свойства KSPROPERTY_JACK_DESCRIPTION.) Дополнительные сведения об этом примере см. в примерах комплекта драйверов Windows.

Фильтр топологии для примера Simple MSVAD определяет три соединительных пина. Эти закрепления перечислены в следующей таблице.

Идентификатор пин-кода Описание

KSPIN_TOPO_SYNTHIN_SOURCE

Разъем ввода MIDI

KSPIN_TOPO_MIC_SOURCE

Разъем ввода микрофона

KSPIN_TOPO_LINEOUT_DEST

Разъём для выхода стереофонических колонок

В оставшейся части данного раздела объясняется, как изменить простой драйвер-пример MSVAD для предоставления сведений о разъемах для трех мостов.

Сначала, сведения о разъеме для этих штифтов можно указать следующим образом:

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

В приведенном выше примере кода члены ChannelMapping задают для двух закреплений записи значение 0. Только аналоговые пин-коды отрисовки должны иметь ненулевое значение ChannelMapping .

Основное изменение примера MSVAD — добавление следующего обработчика свойств в реализацию мини-порта топологии в примере файла 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;
}

Приведенный выше пример кода относится к трем переменным KSJACK_DESCRIPTION — SynthIn_Jack, MicIn_Jack и LineOut_Jack — которые были определены ранее. Если клиент запрашивает фильтр для описания валидной точки, но такой, который не является мостовым пином (и поэтому не имеет описания джека), запрос проходит успешно (со статусом STATUS_SUCCESS), но обработчик свойств возвращает пустое описание джека, состоящее из структуры KSMULTIPLE_ITEM и больше ничего. Если клиент задает недопустимый идентификатор пин-кода (который определяет несуществующий пин-код), обработчик возвращает код состояния STATUS_INVALID_PARAMETER.

Для поддержки свойства KSPROPERTY_JACK_DESCRIPTION требуются два дополнительных изменения в примере Simple MSVAD. К ним относятся:

  • Добавьте объявление метода PropertyHandlerJackDescription в приведенном выше примере кода в определение класса CMiniportTopology в файле заголовка Mintopo.h.

  • Реализуйте таблицу автоматизации для фильтра топологии и загрузите адрес этой таблицы в элемент AutomationTable структуры PCFILTER_DESCRIPTOR в файле заголовка Toptable.h. Эта структура называется MiniportFilterDescriptor.

Чтобы реализовать таблицу автоматизации для фильтра, вставьте следующий код в файл заголовка Toptable.h (до определения MiniportFilterDescriptor):

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

DEFINE_PCAUTOMATION_TABLE_PROP(AutomationTopoFilter, PropertiesTopoFilter);

В предыдущем примере кода элемент обработчика структуры PCPROPERTY_ITEM содержит указатель функции на обработчик свойств, добавленный в Mintopo.cpp на предыдущем шаге. Чтобы сделать обработчик свойств доступным из файла заголовка, вставьте объявление функции extern для PropertyHandler_TopoFilter в начале файла заголовка.

Дополнительные сведения о свойстве описания джека см. в описаниях джека для динамических аудиоустройств.