다음을 통해 공유


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 오디오 코덱의 핀 구성 레지스터에서 읽은 데이터에서 KSPROPERTY_JACK_DESCRIPTION 속성 값을 자동으로 생성합니다. 그러나 모든 KS 기반 오디오 드라이버는 필터 자동화 테이블에서 이 속성에 대한 지원을 구현할 수 있습니다. HD Audio 클래스 드라이버에 대한 자세한 내용은 HD 오디오 및 UAA를 참조하세요. 핀 구성 레지스터에 대한 자세한 내용은 고화질 오디오 디바이스에 대한 핀 구성 지침 백서를 참조하세요.

오디오 엔드포인트 디바이스는 하나 이상의 잭을 통해 브리지 핀에 연결할 수 있습니다. 예를 들어(2 채널) 스테레오 스피커 집합에는 하나의 잭이 필요하지만 5.1 서라운드 사운드 스피커 집합에는 3개의 잭이 필요합니다(각 잭이 6개 채널 중 2개를 처리한다고 가정).

각 잭에 대한 설명은 KSJACK_DESCRIPTION 구조에 포함되어 있습니다. 예를 들어 하나의 잭이 있는 오디오 엔드포인트 디바이스의 KSPROPERTY_JACK_DESCRIPTION 속성 값에는 하나의 KSJACK_DESCRIPTION 구조가 포함되지만, 3개의 잭이 있는 엔드포인트 디바이스의 속성 값에는 세 개의 KSJACK_DESCRIPTION 구조가 포함됩니다. 두 경우 모두 속성 값의 KSJACK_DESCRIPTION 구조체 또는 구조체 앞에는 속성 값의 크기를 지정하는 KSMULTIPLE_ITEM 구조체가 있습니다. 자세한 내용은 KSPROPERTY_JACK_DESCRIPTION 참조하세요.

잭 정보는 사용자가 멀티채널 스피커 구성에 연결하는 잭을 구분하는 데 특히 유용합니다. 다음 코드 예제에서는 오디오 드라이버가 5.1 서라운드 스피커 집합에 대한 3개의 잭을 설명하는 데 사용하는 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 멤버 값이 동일합니다.

WDK의 "Simple" MSVAD 샘플 드라이버(샘플 디렉터리 Src\Audio\Msvad\Simple)는 KSPROPERTY_JACK_DESCRIPTION 속성을 지원하도록 조정할 수 있습니다. 이 샘플 드라이버는 실제 하드웨어가 필요하지 않으므로 속성의 사용을 보여 줍니다. 따라서 Windows를 실행하는 모든 컴퓨터에 설치할 수 있습니다. 그러나 Windows Vista 이상 운영 체제만 KSPROPERTY_JACK_DESCRIPTION 속성을 완전히 지원합니다. 이 샘플에 대한 자세한 내용은 Windows 드라이버 키트 샘플을 참조하세요.

Simple MSVAD 샘플에 대한 토폴로지 필터는 세 개의 브리지 핀을 정의합니다. 이러한 핀은 다음 표에 나와 있습니다.

핀 ID Description

KSPIN_TOPO_SYNTHIN_SOURCE

MIDI 입력 잭

KSPIN_TOPO_MIC_SOURCE

마이크 입력 잭

KSPIN_TOPO_LINEOUT_DEST

스테레오 스피커 출력 잭

이 항목의 나머지 부분에서는 간단한 MSVAD 샘플 드라이버를 수정하여 3개의 브리지 핀에 대한 잭 정보를 제공하는 방법을 설명합니다.

먼저 이러한 핀에 대한 잭 정보를 다음과 같이 지정할 수 있습니다.

// 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으로 설정합니다. 아날로그 렌더링 핀만 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 구조체로 구성된 빈 잭 설명을 반환합니다. 클라이언트가 존재하지 않는 핀을 식별하는 잘못된 핀 ID를 지정하는 경우 처리기는 코드 STATUS_INVALID_PARAMETER 상태 반환합니다.

KSPROPERTY_JACK_DESCRIPTION 속성을 지원하려면 Simple MSVAD 샘플에 대한 두 가지 추가 수정이 필요합니다. 이러한 방법은 다음과 같습니다.

  • 앞의 코드 예제에서 PropertyHandlerJackDescription 메서드의 선언을 헤더 파일 Mintopo.h의 CMiniportTopology 클래스 정의에 추가합니다.

  • 토폴로지 필터에 대한 자동화 테이블을 구현하고 이 테이블의 주소를 헤더 파일 Toptable.h의 PCFILTER_DESCRIPTOR 구조체의 AutomationTable 멤버로 로드합니다. 이 구조체의 이름은 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에 추가된 속성 처리기에 대한 함수 포인터가 포함되어 있습니다. 헤더 파일에서 속성 처리기에 액세스할 수 있도록 하려면 헤더 파일의 시작 부분에 PropertyHandler_TopoFilter 대한 extern 함수 선언을 삽입합니다.

잭 설명 속성에 대한 자세한 내용은 동적 오디오 하위 서비스에 대한 잭 설명을 참조하세요.