ALSA
ALSA のインクルードファイルは、/usr/include/alsa ディレクトリにあります。
alsa/asoundlib.h をインクルードすると、すべてのファイルをインクルードできます。
ライブラリは、libasound です。
-lasound でリンクします。
alsa/asoundlib.h をインクルードすると、すべてのファイルをインクルードできます。
#include <alsa/asoundlib.h>
ライブラリは、libasound です。
-lasound でリンクします。
ALSA の情報
ALSA の情報は、/proc/asound/ ディレクトリ内に、ファイルとして出力されています。
$ ls /proc/asound PCH card0 cards devices hwdep modules oss pcm seq timers version
cards
/proc/asound/cards のテキストファイルを見てみると、物理的なサウンドカードの情報がリスト化されています。
この情報は、以下のような形式で出力されています。
$ cat /proc/asound/cards 0 [PCH ]: HDA-Intel - HDA Intel PCH HDA Intel PCH at 0xdf140000 irq 130
この情報は、以下のような形式で出力されています。
index [ID]: Driver - name longname
カードの情報
まずは、ALSA で、サウンドカードの情報を取得してみたいと思います。
ALSA でサウンドカードの制御を行うには、コントロールインターフェイスを使って、サウンドカードを開き、snd_ctl_t のハンドラを取得する必要があります。
そのためには、カードのインデックス番号か、名前が必要になります。
ALSA でサウンドカードの制御を行うには、コントロールインターフェイスを使って、サウンドカードを開き、snd_ctl_t のハンドラを取得する必要があります。
そのためには、カードのインデックス番号か、名前が必要になります。
サウンドカードの列挙
snd_card_next() を使って、物理的なサウンドカードのインデックス番号を列挙することができます。
card にカードのインデックスをセットして実行すると、次のカードインデックスを、card に返します。
戻り値は、0 で成功。負の値でエラーコードです。
card に -1 を指定すると、最初のカードのインデックスが返ります。
card に -1 が返った場合は、終端です。
カードが2つ (index = 0, 1) ある場合、card に指定する値と、card に返る値は、以下のようになります。
int snd_card_next(int *card);
card にカードのインデックスをセットして実行すると、次のカードインデックスを、card に返します。
戻り値は、0 で成功。負の値でエラーコードです。
card に -1 を指定すると、最初のカードのインデックスが返ります。
card に -1 が返った場合は、終端です。
カードが2つ (index = 0, 1) ある場合、card に指定する値と、card に返る値は、以下のようになります。
-1 -> 0 0 -> 1 1 -> -1
インデックスから名前を取得
カードのインデックスから、カードの名前を取得する場合は、以下の関数を使います。
name には、strdup で複製された文字列のポインタが返るので、free() で解放する必要があります。
name は、"HDA Intel PCH"。
longname は、"HDA Intel PCH at 0xdf140000 irq 130" というような文字列になります。
int snd_card_get_name(int card, char **name); int snd_card_get_longname(int card, char **name);
name には、strdup で複製された文字列のポインタが返るので、free() で解放する必要があります。
name は、"HDA Intel PCH"。
longname は、"HDA Intel PCH at 0xdf140000 irq 130" というような文字列になります。
エラー
ALSA の関数の戻り値は、基本的に、0 で成功、負の値でエラーコードになります。
エラーコードは、errno を負にした値になります (-EAGAIN など)。
取得した値を返すような関数以外で、戻り値を明記していない場合は、このルールとなります。
エラーコードから、説明用の文字列を取得します。
エラー時に実行されるハンドラをセットします。
デフォルト (handler = NULL) の場合、stderr にエラーメッセージが出力されます。
エラーコードは、errno を負にした値になります (-EAGAIN など)。
取得した値を返すような関数以外で、戻り値を明記していない場合は、このルールとなります。
エラーコードから文字列取得
const char *snd_strerror(int errnum);
エラーコードから、説明用の文字列を取得します。
エラーハンドラ
int snd_lib_error_set_handler(snd_lib_error_handler_t handler); typedef void (*snd_lib_error_handler_t)(const char *file, int line, const char *function, int err, const char *fmt, ...);
エラー時に実行されるハンドラをセットします。
デフォルト (handler = NULL) の場合、stderr にエラーメッセージが出力されます。
snd_ctl_t の取得
カードのインデックスを元に取得できるのは、名前の情報だけです。
カードのより詳細な情報を取得したい場合は、コントロールインターフェイスを使います。
まずは、カードのインデックスを元に、コントロール用に、サウンドカードを開きます。
サウンドカードを開き、*ctl に snd_ctl_t ハンドラを返します。
カードのインデックス番号を指定して開きたい場合は、"hw:<index>"。
カードの ID 文字列を指定して開きたい場合は、"hw:CARD=<ID>" という形式で指定します。
例: "hw:0", "hw:CARD=PCH"
"hw" は、ハードウェアを意味します。
snd_ctl_t を閉じて、解放します。
カードのより詳細な情報を取得したい場合は、コントロールインターフェイスを使います。
まずは、カードのインデックスを元に、コントロール用に、サウンドカードを開きます。
開く
int snd_ctl_open(snd_ctl_t **ctl, const char *name, int mode);
サウンドカードを開き、*ctl に snd_ctl_t ハンドラを返します。
name | 開くサウンドカードの定義名 |
---|---|
mode | 開くモード。 0 でブロックモードです。 SND_CTL_NONBLOCK : 非ブロッキングモード SND_CTL_ASYNC : 非同期通知 |
カードの名前
ALSA 設定ファイルで定義されている、デフォルトのカードを指定する場合は、"default" を指定します。カードのインデックス番号を指定して開きたい場合は、"hw:<index>"。
カードの ID 文字列を指定して開きたい場合は、"hw:CARD=<ID>" という形式で指定します。
例: "hw:0", "hw:CARD=PCH"
"hw" は、ハードウェアを意味します。
閉じる
int snd_ctl_close(snd_ctl_t *ctl);
snd_ctl_t を閉じて、解放します。
カードの情報取得
snd_ctl_t が取得できたら、カードの情報を取得します。
カードの情報を、snd_ctl_card_info_t に取得します。
snd_ctl_card_info_t は、メンバが非公開な形になっているので、構造体として直接使用することができません。
この関数を実行する前に、snd_ctl_card_info_t のメモリを確保する必要があります。
カードの情報取得
int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info);
カードの情報を、snd_ctl_card_info_t に取得します。
snd_ctl_card_info_t は、メンバが非公開な形になっているので、構造体として直接使用することができません。
この関数を実行する前に、snd_ctl_card_info_t のメモリを確保する必要があります。
snd_ctl_card_info_t の確保
ALSA で取得できる情報は、基本的にメンバが非公開なものが多いので、そのような情報では、データを取得する前に、メモリを確保する必要があります。
サイズを取得して自分で確保するか、専用の確保関数と解放関数を使います。
サイズを取得して自分で確保するか、専用の確保関数と解放関数を使います。
//サイズの取得 size_t snd_ctl_card_info_sizeof(void); //確保 int snd_ctl_card_info_malloc(snd_ctl_card_info_t **ptr); //解放 void snd_ctl_card_info_free(snd_ctl_card_info_t *obj);
各値の取得
snd_ctl_card_info() で情報を取得したら、関数を使って、snd_ctl_card_info_t から各値を取得します。
//カードインデックス int snd_ctl_card_info_get_card(const snd_ctl_card_info_t *obj); //ID 文字列 const char *snd_ctl_card_info_get_id(const snd_ctl_card_info_t *obj); //ドライバ名 const char *snd_ctl_card_info_get_driver(const snd_ctl_card_info_t *obj); //名前 const char *snd_ctl_card_info_get_name(const snd_ctl_card_info_t *obj); //長い名前 const char *snd_ctl_card_info_get_longname(const snd_ctl_card_info_t *obj); //ミキサー名 const char *snd_ctl_card_info_get_mixername(const snd_ctl_card_info_t *obj); //コンポーネントプロパティ const char *snd_ctl_card_info_get_components(const snd_ctl_card_info_t *obj);
プログラム
snd_ctl_card_info_t のサイズと、各サウンドカードの情報を出力するプログラムです。
$ cc -o 01_cardinfo 01_cardinfo.c -lasound
#include <stdio.h> #include <alsa/asoundlib.h> int main(void) { int card; snd_ctl_t *ctl; snd_ctl_card_info_t *info; char m[16]; printf("size: %d\n", (int)snd_ctl_card_info_sizeof()); card = -1; while(snd_card_next(&card) == 0) { if(card == -1) break; printf("--- [%d] ---\n", card); //開く snprintf(m, 16, "hw:%d", card); if(snd_ctl_open(&ctl, m, 0)) break; //情報取得 snd_ctl_card_info_malloc(&info); snd_ctl_card_info(ctl, info); // printf("ID: %s\n", snd_ctl_card_info_get_id(info)); printf("driver: %s\n", snd_ctl_card_info_get_driver(info)); printf("name: %s\n", snd_ctl_card_info_get_name(info)); printf("longname: %s\n", snd_ctl_card_info_get_longname(info)); printf("mixername: %s\n", snd_ctl_card_info_get_mixername(info)); printf("components: %s\n", snd_ctl_card_info_get_components(info)); //閉じる snd_ctl_card_info_free(info); snd_ctl_close(ctl); } return 0; }
出力結果
size: 376 --- [0] --- ID: PCH driver: HDA-Intel name: HDA Intel PCH longname: HDA Intel PCH at 0xdf140000 irq 130 mixername: Realtek ALC892 components: HDA:10ec0892,18495892,00100302 HDA:80862809,80860101,00100000