PCM 定義名
PCM を開く場合は、name 引数で、PCM の定義名を指定する必要があります。
デフォルトの PCM を使う場合は "default" を指定しますが、ここでは、この名前に関する詳細を説明していきます。
デフォルトの PCM を使う場合は "default" を指定しますが、ここでは、この名前に関する詳細を説明していきます。
ALSA の定義
ALSA の定義ファイルは、/usr/share/alsa/ ディレクトリにあり、メインとなる alsa.conf で、各インターフェイスの定義などが行われています。
見ていると、何となくわかるように、@args で引数の指定があり、各引数では、デフォルトの値が指定されています。
この定義により、hw には、CARD, DEV, SUBDEV の引数があるのがわかります。
ALSA で PCM インターフェイスを開く際に、この pcm.hw を開きたい場合、"pcm." はインターフェイスを指定する部分なので省略し、"hw" の文字列を指定します。
さらに hw の引数を指定したい場合は、"hw" の後に ":" を付けて、その後、複数の値を、カンマで区切って指定します。
この場合、値の順番は、@args で定義されている通り、CARD, DEV, SUBDEV の順番となります。
なお、引数の名前と値を指定したい場合は、NAME=VAL の形式で、"hw:CARD=0,DEV=0" というように指定します。
alsa.conf では、以下のように、デフォルトの値が指定されているので、"hw" とだけ指定した場合、CARD, DEV, SUBDEV の値は、0, 0, -1 (任意) というようになります。
ユーザーが、ALSA のデフォルトのカードやデバイスを指定したい場合は、ここを編集します。
CARD で指定するのは、カードのインデックス番号か、ID (snd_ctl_card_info_get_id()) の名前です。
特定のカードのデバイス番号を列挙したい場合は、コントロールインターフェイスの snd_ctl_pcm_next_device() を使います。
サブデバイス番号は、PCM 情報から、有効なサブデバイス番号の数を取得できます。
PCM インターフェイス
alsa.conf 内の、PCM インターフェイスの定義部分を見てみます。
最初にあるのは、"pcm.hw" の定義です。
pcm.hw は、PCM ハードウェアを意味し、サンプルの変換などを行わず、ALSA カーネルドライバと直接通信するためのものです。
pcm.plughw の場合は、変換が有効な hw です。
pcm.null は、無音状態を再生したり、無音を録音する時に使います。
最初にあるのは、"pcm.hw" の定義です。
pcm.hw は、PCM ハードウェアを意味し、サンプルの変換などを行わず、ALSA カーネルドライバと直接通信するためのものです。
pcm.plughw の場合は、変換が有効な hw です。
pcm.null は、無音状態を再生したり、無音を録音する時に使います。
pcm.hw の定義
pcm.hw { # 引数 @args [ CARD DEV SUBDEV ] # CARD 引数 @args.CARD { type string # デフォルト値 default { # 環境変数から取得 @func getenv vars [ ALSA_PCM_CARD ALSA_CARD ] default { # コピー @func refer name defaults.pcm.card } } } # DEV 引数 @args.DEV { type integer default { @func igetenv vars [ ALSA_PCM_DEVICE ] default { @func refer name defaults.pcm.device } } } # SUBDEV 引数 @args.SUBDEV { type integer default { @func refer name defaults.pcm.subdevice } } type hw card $CARD device $DEV subdevice $SUBDEV # 名前ヒント hint { show { @func refer name defaults.namehint.extended } description "Direct hardware device without any conversions" } }
見ていると、何となくわかるように、@args で引数の指定があり、各引数では、デフォルトの値が指定されています。
この定義により、hw には、CARD, DEV, SUBDEV の引数があるのがわかります。
ALSA で PCM インターフェイスを開く際に、この pcm.hw を開きたい場合、"pcm." はインターフェイスを指定する部分なので省略し、"hw" の文字列を指定します。
さらに hw の引数を指定したい場合は、"hw" の後に ":" を付けて、その後、複数の値を、カンマで区切って指定します。
この場合、値の順番は、@args で定義されている通り、CARD, DEV, SUBDEV の順番となります。
なお、引数の名前と値を指定したい場合は、NAME=VAL の形式で、"hw:CARD=0,DEV=0" というように指定します。
デフォルトの値
省略された引数は、定義で指定されている通り、デフォルトの値が使用されます。alsa.conf では、以下のように、デフォルトの値が指定されているので、"hw" とだけ指定した場合、CARD, DEV, SUBDEV の値は、0, 0, -1 (任意) というようになります。
defaults.pcm.card 0 defaults.pcm.device 0 defaults.pcm.subdevice -1
ユーザーが、ALSA のデフォルトのカードやデバイスを指定したい場合は、ここを編集します。
PCM を開く時の名前の例
hw # hw:0,0,-1 hw:0 hw:0,0 hw:0,0,0 hw:CARD=PCH # カードの ID 名 hw:CARD=0,DEV=0,SUBDEV=0
CARD で指定するのは、カードのインデックス番号か、ID (snd_ctl_card_info_get_id()) の名前です。
特定のカードのデバイス番号を列挙したい場合は、コントロールインターフェイスの snd_ctl_pcm_next_device() を使います。
int snd_ctl_pcm_next_device(snd_ctl_t *ctl, int *device);
サブデバイス番号は、PCM 情報から、有効なサブデバイス番号の数を取得できます。
デフォルト
PCM 関連のデフォルトは、以下のように指定されています。
cards は、/usr/share/alsa/cards/ で、各サウンドカードごとの定義ファイルがあります。
PCM で "default" を開いた場合は、実際には pcm.default、つまり cards.pcm.default (カードごとのデフォルト) が使われることになります。
"default" は、ユーザー設定でのデフォルト。
"sysdefault" は、システム設定でのデフォルトとなります。
HDMI に出力したい場合は、"hdmi" で指定できます。
cards は、/usr/share/alsa/cards/ で、各サウンドカードごとの定義ファイルがあります。
pcm.default cards.pcm.default pcm.sysdefault cards.pcm.default pcm.front cards.pcm.front pcm.rear cards.pcm.rear pcm.center_lfe cards.pcm.center_lfe pcm.side cards.pcm.side pcm.surround21 cards.pcm.surround21 pcm.surround40 cards.pcm.surround40 pcm.surround41 cards.pcm.surround41 pcm.surround50 cards.pcm.surround50 pcm.surround51 cards.pcm.surround51 pcm.surround71 cards.pcm.surround71 pcm.iec958 cards.pcm.iec958 pcm.spdif iec958 pcm.hdmi cards.pcm.hdmi pcm.dmix cards.pcm.dmix pcm.dsnoop cards.pcm.dsnoop pcm.modem cards.pcm.modem pcm.phoneline cards.pcm.phoneline
PCM で "default" を開いた場合は、実際には pcm.default、つまり cards.pcm.default (カードごとのデフォルト) が使われることになります。
"default" は、ユーザー設定でのデフォルト。
"sysdefault" は、システム設定でのデフォルトとなります。
HDMI に出力したい場合は、"hdmi" で指定できます。
名前ヒント
名前ヒントは、コントロールや PCM など、ALSA の各インターフェイスを開く時に指定する、定義名のことです。
一般的に使用可能な定義名を、一覧で取得することができます。
指定したカードの、名前ヒントのセットを取得します。
snd_device_name_hint() で取得したポインタを解放します。
各ヒントのポインタから、値を取得します。
一般的に使用可能な定義名を、一覧で取得することができます。
名前ヒントのセットを取得
int snd_device_name_hint(int card, const char *iface, void ***hints);
指定したカードの、名前ヒントのセットを取得します。
card | カードのインデックス番号。-1 ですべて |
---|---|
iface | ALSA のインターフェイス名。 "ctl" や "pcm" など。 |
hints | 名前ヒントの配列のポインタが返る。 配列の値が NULL で、データの終端。 |
解放
int snd_device_name_free_hint(void **hints);
snd_device_name_hint() で取得したポインタを解放します。
情報の取得
char *snd_device_name_get_hint(const void *hint, const char *id);
各ヒントのポインタから、値を取得します。
id | 取得する値の定義名。 "NAME" : デバイスの名前 "DESC" : デバイスの詳細説明 "IOID" : 入力または出力か ("Input" または "Output" が返る)。NULL が返ると、両方。 |
---|---|
戻り値 | 確保された ASCII 文字列。 free() で解放する。 NULL が返る場合もある。 |
プログラム
引数で指定したインターフェイス (省略で "pcm") の、すべての名前ヒントを出力します。
$ cc -o 09-namehint 09-namehint.c -lasound
#include <stdlib.h> #include <stdio.h> #include <alsa/asoundlib.h> int main(int argc,char **argv) { void **hints; const char *id[] = {"NAME", "DESC", "IOID"}; int i,j; char *str; if(snd_device_name_hint(-1, (argc >= 2)? argv[1]: "pcm", &hints)) return 0; for(i = 0; hints[i]; i++) { printf("-- [%d] --\n", i); for(j = 0; j < 3; j++) { str = snd_device_name_get_hint(hints[i], id[j]); printf("%s: ", id[j]); if(str) printf("'%s'\n", str); else printf("<null>\n"); if(str) free(str); } } snd_device_name_free_hint(hints); return 0; }
実行結果
-- [0] -- NAME: 'null' DESC: 'Discard all samples (playback) or generate zero samples (capture)' IOID: <null> -- [1] -- NAME: 'default:CARD=PCH' DESC: 'HDA Intel PCH, ALC892 Analog Default Audio Device' IOID: <null> -- [2] -- NAME: 'sysdefault:CARD=PCH' DESC: 'HDA Intel PCH, ALC892 Analog Default Audio Device' IOID: <null> -- [3] -- NAME: 'front:CARD=PCH,DEV=0' DESC: 'HDA Intel PCH, ALC892 Analog Front output / input' IOID: <null> -- [4] -- NAME: 'surround21:CARD=PCH,DEV=0' DESC: 'HDA Intel PCH, ALC892 Analog 2.1 Surround output to Front and Subwoofer speakers' IOID: 'Output' -- [5] -- NAME: 'surround40:CARD=PCH,DEV=0' DESC: 'HDA Intel PCH, ALC892 Analog 4.0 Surround output to Front and Rear speakers' IOID: 'Output' -- [6] -- NAME: 'surround41:CARD=PCH,DEV=0' DESC: 'HDA Intel PCH, ALC892 Analog 4.1 Surround output to Front, Rear and Subwoofer speakers' IOID: 'Output' -- [7] -- NAME: 'surround50:CARD=PCH,DEV=0' DESC: 'HDA Intel PCH, ALC892 Analog 5.0 Surround output to Front, Center and Rear speakers' IOID: 'Output' -- [8] -- NAME: 'surround51:CARD=PCH,DEV=0' DESC: 'HDA Intel PCH, ALC892 Analog 5.1 Surround output to Front, Center, Rear and Subwoofer speakers' IOID: 'Output' -- [9] -- NAME: 'surround71:CARD=PCH,DEV=0' DESC: 'HDA Intel PCH, ALC892 Analog 7.1 Surround output to Front, Center, Side, Rear and Woofer speakers' IOID: 'Output' -- [10] -- NAME: 'hdmi:CARD=PCH,DEV=0' DESC: 'HDA Intel PCH, PHL 224E5 HDMI Audio Output' IOID: 'Output' -- [11] -- NAME: 'hdmi:CARD=PCH,DEV=1' DESC: 'HDA Intel PCH, HDMI 1 HDMI Audio Output' IOID: 'Output' -- [12] -- NAME: 'hdmi:CARD=PCH,DEV=2' DESC: 'HDA Intel PCH, HDMI 2 HDMI Audio Output' IOID: 'Output'
"null" は、カードに関係なく存在します。
IOID が null の場合は、再生/録音どちらでも使えます。
CARD=PCH は、実際に存在するサウンドカードです。
DEV の指定がない場合は、デフォルトのデバイス (ユーザーが設定で選択可能) となります。
PCM を開く場合、NAME の文字列を指定することができます。
HDMI
"hdmi" を指定した場合、デバイス番号が 0,1,2 となっていますが、PCM 情報で "hdmi" を指定した時、実際のデバイス番号は3でした。
ALSA 定義における pcm.hdmi は、別途異なる形で定義されているので、hdmi の引数 DEV は、カードの実際のデバイス番号とは異なります。
例えば、カードが HDA-Intel の場合は、hdmi のデバイス 0 は、DEVICE=3 として定義されています。
ALSA 定義における pcm.hdmi は、別途異なる形で定義されているので、hdmi の引数 DEV は、カードの実際のデバイス番号とは異なります。
例えば、カードが HDA-Intel の場合は、hdmi のデバイス 0 は、DEVICE=3 として定義されています。
HDA-Intel.pcm.hdmi.0 { @args [ CARD AES0 AES1 AES2 AES3 ] @args.CARD { type string } ... @func refer name { @func concat strings [ "cards.HDA-Intel.pcm.hdmi.common:" "CARD=" $CARD "," "DEVICE=3," "CTLINDEX=0," ... ] } }
コントロールの名前ヒント
名前ヒントで "ctl" を指定すると、コントロールインターフェイスを開く時の名前を取得できます。
$ ./09-namehint ctl -- [0] -- NAME: 'default' DESC: 'Default Control Device' IOID: <null> -- [1] -- NAME: 'sysdefault' DESC: 'Default Control Device' IOID: <null> -- [2] -- NAME: 'hw' DESC: 'Direct control device' IOID: <null> -- [3] -- NAME: 'default:CARD=PCH' DESC: 'HDA Intel PCH Default Control Device' IOID: <null> -- [4] -- NAME: 'sysdefault:CARD=PCH' DESC: 'HDA Intel PCH Default Control Device' IOID: <null> -- [5] -- NAME: 'hw:CARD=PCH' DESC: 'HDA Intel PCH Direct control device' IOID: <null>