ジャック説明のプロパティ
Windows Vista 以降では、KSPROPERTY_JACK_DESCRIPTION プロパティは、オーディオ アダプター上のオーディオ ジャックまたはその他の物理コネクタを表します。 プロパティ値は、ジャックの色、ジャックの物理的な位置、コネクタの種類、その他のジャック機能を表しています。 この情報の目的は、ユーザーがマイク、ヘッドフォン、スピーカーなどのオーディオ エンドポイント デバイスに接続するための正しいジャックを見つけるのに役立ちます。 詳しくは、「オーディオ エンドポイント デバイス」をご覧ください。
オーディオ アダプターの KS フィルターが KSPROPERTY_JACK_DESCRIPTION プロパティをサポートしている場合、Windows マルチメディア コントロール パネルの Mmsys.cpl には、フィルターのブリッジ ピンのジャック情報が表示されます。 ブリッジ ピンは、オーディオ エンドポイント デバイスへの接続 (通常はジャック) を表しています。 プロパティ値には、ピン (つまり、ピンに関連付けられているジャック) に関する情報が含まれていますが、プロパティはピンではなくフィルターのプロパティです。 ブリッジ ピンの詳細については、「オーディオ フィルター グラフ」を参照してください。 フィルターのプロパティとピンのプロパティについて詳しくは、「フィルター、ピン、およびノードのプロパティ」をご覧ください。
オーディオ アプリケーションは、DeviceTopology API で IKsJackDescription::GetJackDescription メソッドを呼び出すことによって、オーディオ エンドポイント デバイスのKSPROPERTY_JACK_DESCRIPTION プロパティ値を取得できます。 たとえば、アプリケーションはジャック情報を使用し、緑色の XLR ジャックに接続されたマイクと、オレンジ色の XLR ジャックに接続されたマイクを区別するのに役立ちます。 DeviceTopology API について詳しくは、「デバイス トポロジ」をご覧ください。
マイクロソフトの HD オーディオ クラス ドライバーは、HD オーディオ コーデックにおいてピン構成レジスタから読み取ったデータから KSPROPERTY_JACK_DESCRIPTION プロパティ値を自動的に構築します。 ただし、KS ベースのオーディオ ドライバーは、フィルター オートメーション テーブルでこのプロパティのサポートを実装できます。 HD オーディオ クラス ドライバーについて詳しくは、「HD オーディオと UAA」をご覧ください。 ピン構成レジスタについて詳しくは、「高品位オーディオ デバイスのピン構成ガイドライン」ホワイト ペーパーをご覧ください。
オーディオ エンドポイント デバイスは、1 つ以上のジャックを通じてブリッジ ピンに接続できます。 たとえば、一連の (2 チャンネル) ステレオ スピーカーには 1 つのジャックが必要ですが、5.1 サラウンド サウンド スピーカーのセットには 3 つのジャックが必要です (各ジャックが、6 つのチャンネルのうち 2 つを処理すると仮定します)。
各ジャックの説明は、KSJACK_DESCRIPTION 構造に含まれています。 たとえば、1 つのジャックを持つオーディオ エンドポイント デバイスの KSPROPERTY_JACK_DESCRIPTION プロパティ値には、1 つの KSJACK_DESCRIPTION 構造が含まれていますが、3 つのジャックを持つエンドポイント デバイスのプロパティ値には 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 で定義されています。
加えて、ジャックの説明の配列を使用して、2 つ以上のジャックが互いに機能的に同等であることを示すことができます。 次のコード例では、オーディオ ドライバーは、黄色の RCA ジャックと黒のデジタル光学ジャックのジャックの説明を 1 つの配列に結合して、2 つのジャックが同じ信号を運搬することをユーザーに示しています。
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
}
};
前のコード例では、2 つの KSJACK_DESCRIPTION 構造の ChannelMapping メンバーの値は同じです。
WDK の "シンプルな" MSVAD サンプル ドライバー (サンプル ディレクトリ Src\Audio\Msvad\Simple) は、KSPROPERTY_JACK_DESCRIPTION プロパティをサポートするよう調整できます。 このサンプル ドライバーは、実際のハードウェアを必要としないため、プロパティの使用方法を示すのに便利です。 したがって、Windows を実行している任意のコンピューターにインストールできます。 (ただし、KSPROPERTY_JACK_DESCRIPTION プロパティを完全にサポートできるのは、Windows Vista 以降のオペレーティング システムのみです)。このサンプルについて詳しくは、「Windows Driver Kit のサンプル」をご覧ください。
シンプルな MSVAD サンプルのトポロジ フィルターは、3 つのブリッジ ピンを定義します。 次の表に、該当するピンの一覧を示します。
ピン ID | 説明 |
---|---|
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
}
};
前のコード例では、2 つのキャプチャ ピンの ChannelMapping メンバーを 0 に設定します。 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;
}
前のコード例は、前に定義した 3 つの KSJACK_DESCRIPTION 変数 (SynthIn_Jack、MicIn_Jack、LineOut_Jack) に言及しています。 クライアントが有効なピンのジャック説明のフィルターに対してクエリを実行するが、ブリッジ ピンではない (したがってジャック説明がない) フィルターにはクエリを実行しない場合、クエリは成功します (ステータス コードが STATUS_SUCCESS)。ただし、プロパティ ハンドラーは、KSMULTIPLE_ITEM 構造で構成される空のジャック説明を返し、他には何も返しません。 クライアントが (存在しないピンを識別する) 無効なピン ID を指定した場合、ハンドラーはステータス コード STATUS_INVALID_PARAMETER を返します。
KSPROPERTY_JACK_DESCRIPTION プロパティをサポートするには、シンプルな MSVAD サンプルに対して 2 つの追加の変更が必要になります。 次のとおりです。
前のコード例の 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 構造の Handler メンバーに、前の手順で Mintopo.cpp に追加されたプロパティ ハンドラーへの関数ポインターが含まれています。 ヘッダー ファイルからプロパティ ハンドラーにアクセス可能にするには、ヘッダー ファイルの先頭に PropertyHandler_TopoFilter の extern 関数宣言を挿入します。
ジャック説明プロパティについて詳しくは、「動的オーディオ サブデバイスのジャック説明」をご覧ください。