Jack Description 屬性

在 Windows Vista 和更新版本中, KSPROPERTY_JACK_DESCRIPTION 屬性描述音訊配接器上的音訊插孔或其他實體連接器。 屬性值描述插孔的色彩、插孔的實體位置、連接器類型和其他插孔功能。 這項資訊的目的是協助使用者尋找正確的插接器,以插入麥克風、耳機或喇叭等音訊端點裝置。 如需詳細資訊,請參閱 音訊端點裝置

如果音訊介面卡上的 KS 篩選器支援 KSPROPERTY_JACK_DESCRIPTION 屬性,Windows 多媒體控制台Mmsys.cpl會顯示篩選上橋接器接腳的插孔資訊。 橋接器接腳代表連接 (通常是音訊端點裝置) 。 雖然 屬性值包含針腳 (的相關資訊,或是與針腳) 相關聯的插孔或插腳,但屬性是篩選的屬性,而不是針腳。 如需橋接器接腳的詳細資訊,請參閱 音訊篩選圖形。 如需篩選屬性和釘選屬性的詳細資訊,請參閱 篩選、釘選和節點屬性

音訊應用程式可以在 DeviceTopology API 中呼叫 IKsJackDescription::GetJackDescription 方法,以取得音訊端點裝置的KSPROPERTY_JACK_DESCRIPTION屬性值。 例如,應用程式可以使用插孔資訊來協助使用者區分插入綠色 XLR 插孔的麥克風,以及插入橙色 XLR 插孔的麥克風。 如需 DeviceTopology API 的詳細資訊,請參閱 裝置拓撲

Microsoft HD Audio 類別驅動程式會自動從 HD Audio 編解碼器中釘選組態暫存器讀取的資料建構KSPROPERTY_JACK_DESCRIPTION屬性值。 不過,任何 KS 型音訊驅動程式都可以在其篩選自動化資料表中實作此屬性的支援。 如需 HD 音訊類別驅動程式的詳細資訊,請參閱 HD 音訊和 UAA。 如需釘選組態暫存器的詳細資訊,請參閱 高畫質音訊裝置的釘選設定指導方針 白皮書。

音訊端點裝置可以透過一或多個插接器連線到橋接器接腳。 例如,一組 (雙聲道) 身歷聲喇叭需要一個插孔,但一組 5.1 環繞音效喇叭需要三個插孔, (假設每個插孔處理六個通道) 的兩個。

每個插孔的描述都包含在 KSJACK_DESCRIPTION 結構中。 例如,具有一個插孔的音訊端點裝置KSPROPERTY_JACK_DESCRIPTION屬性值包含一個KSJACK_DESCRIPTION結構,但具有三個插孔的端點裝置屬性值包含三個KSJACK_DESCRIPTION結構。 不論是哪一種情況,屬性值中的KSJACK_DESCRIPTION結構或結構前面都有指定屬性值大小的 KSMULTIPLE_ITEM 結構。 如需詳細資訊,請參閱 KSPROPERTY_JACK_DESCRIPTION

插接器資訊特別適用于協助使用者區分連接到多通道喇叭設定的插孔。 下列程式碼範例顯示音訊驅動程式用來描述一組 5.1 環繞喇叭三個插孔的KSJACK_DESCRIPTION結構陣列:

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 來讀取 KSJACK_DESCRIPTION2 結構的 JackCapabilities 旗標。 如果此旗標已設定JACKDESC2_PRESENCE_DETECT_CAPABILITY位,表示端點確實支援插孔存在偵測。 在此情況下, IsConnected 成員的值可以解譯為插孔插入狀態的精確反映。

上述結構中顯示的 RGB 巨集定義于 Windows SDK 的標頭檔 Wingdi.h 中。

此外,插孔描述的陣列可用來顯示兩個以上的插孔在功能上相當於彼此。 在下列程式碼範例中,音訊驅動程式會將黃色 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
    }
};

在上述程式碼範例中,兩個KSJACK_DESCRIPTION結構中的 ChannelMapping 成員值完全相同。

在範例目錄 Src\Audio\Msvad\Simple) 中,WDK (中的 「Simple」 MSVAD 範例驅動程式可以調整為支援 KSPROPERTY_JACK_DESCRIPTION 屬性。 此範例驅動程式方便示範屬性的使用,因為它不需要實際的硬體。 因此,它可以安裝在任何執行 Windows 的電腦上。 (不過,只有 Windows Vista 和更新版本的作業系統提供KSPROPERTY_JACK_DESCRIPTION屬性的完整支援。) 如需此範例的詳細資訊,請參閱 Windows 驅動程式套件範例

簡單 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。

需要對 Simple MSVAD 範例進行兩項額外的修改,才能支援 KSPROPERTY_JACK_DESCRIPTION 屬性。 這些節點為:

  • 將上述程式碼範例中的 PropertyHandlerJackDescription 方法宣告新增至標頭檔 Mintopo.h 中的 CMiniportTopology 類別定義。

  • 實作拓撲篩選的自動化資料表,並將此資料表的位址載入標頭檔 Toptable.h 中PCFILTER_DESCRIPTOR結構的AutomationTable成員。 此結構名為 MiniportFilterDescriptor

若要實作篩選的自動化資料表,請在 MiniportFilterDescriptor 定義) 之前,將下列程式碼插入標頭檔 Toptable.h (:

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結構的Handler成員包含上一個步驟中新增至 Mintopo.cpp 之屬性處理常式的函式指標。 若要讓屬性處理常式可從標頭檔存取,請在標頭檔開頭插入PropertyHandler_TopoFilter 的 extern 函式宣告。

如需有關插孔描述屬性的詳細資訊,請參閱 動態音訊子裝置的 Jack Descriptions