Поделиться через


Описание Джека

В 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 в windows SDK.

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

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

В оставшейся части этого раздела объясняется, как изменить пример драйвера Simple 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 .

Основное изменение примера Simple 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);

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

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