ALSA:要素の値

要素の値
次は、要素の値を取得してみます。

要素の値は、snd_ctl_elem_value_t に格納されます。

関数の一覧は、要素:値 を参照してください。
snd_ctl_elem_value_t 確保
//サイズ取得
size_t snd_ctl_elem_value_sizeof(void);

//確保
int snd_ctl_elem_value_malloc(snd_ctl_elem_value_t **ptr);

//解放
void snd_ctl_elem_value_free(snd_ctl_elem_value_t *obj);
要素の識別子をセット
snd_ctl_elem_info_t の時と同じように、値を読み込む前に、読み込みたい要素の識別子を、snd_ctl_elem_value_t にセットします。

void snd_ctl_elem_value_set_id(snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_t *ptr);

void snd_ctl_elem_value_set_numid(snd_ctl_elem_value_t *obj, unsigned int val);

void snd_ctl_elem_value_set_interface(snd_ctl_elem_value_t *obj, snd_ctl_elem_iface_t val);
void snd_ctl_elem_value_set_device(snd_ctl_elem_value_t *obj, unsigned int val);
void snd_ctl_elem_value_set_subdevice(snd_ctl_elem_value_t *obj, unsigned int val);
void snd_ctl_elem_value_set_name(snd_ctl_elem_value_t *obj, const char *val);
void snd_ctl_elem_value_set_index(snd_ctl_elem_value_t *obj, unsigned int val);
値の読み込み
int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *data);

要素の値を読み込みます。
値の取得
//真偽値
int snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t *obj, unsigned int idx);

//数値
long snd_ctl_elem_value_get_integer(const snd_ctl_elem_value_t *obj, unsigned int idx);

//64bit数値
long long snd_ctl_elem_value_get_integer64(const snd_ctl_elem_value_t *obj, unsigned int idx);

//列挙型の現在のインデックス
unsigned int snd_ctl_elem_value_get_enumerated(const snd_ctl_elem_value_t *obj, unsigned int idx);

//単一バイト
unsigned char snd_ctl_elem_value_get_byte(const snd_ctl_elem_value_t *obj, unsigned int idx);

//バイトデータ
const void *snd_ctl_elem_value_get_bytes(const snd_ctl_elem_value_t *obj);

//IEC958 データ
void snd_ctl_elem_value_get_iec958(const snd_ctl_elem_value_t *obj, snd_aes_iec958_t *ptr);

typedef struct snd_aes_iec958 {
    unsigned char status[24];   
    unsigned char subcode[147]; 
    unsigned char pad;      
    unsigned char dig_subframe[4];  
} snd_aes_iec958_t;

値のタイプごとに、対応した関数を使って、値を取得します。

IEC958 は、オーディオをデジタル転送するためのデータです。
snd_aes_iec958_t は構造体となっているので、直接値を操作できます。
プログラム
指定したサウンドカード (省略で "default") の、すべての要素の値を出力します。

$ cc -o 04_elemval 04_elemval.c -lasound

#include <stdio.h>
#include <alsa/asoundlib.h>

static void _put_bytes(const char *mes,const void *ptr,int bytes)
{
    const uint8_t *ps = (const uint8_t *)ptr;

    if(mes) printf("[%s] ", mes);

    for(; bytes; bytes--, ps++)
        printf("%02X:", *ps);

    printf("\n");
}

int main(int argc,char **argv)
{
    snd_ctl_t *ctl;
    snd_ctl_elem_list_t *list;
    snd_ctl_elem_info_t *info;
    snd_ctl_elem_value_t *value;
    uint32_t i,j,cnt,tp,valcnt,numid;
    snd_aes_iec958_t iec;

    if(snd_ctl_open(&ctl, (argc >= 2)? argv[1]: "default", 0))
        return 1;

    //リスト取得

    snd_ctl_elem_list_malloc(&list);

    snd_ctl_elem_list(ctl, list);

    cnt = snd_ctl_elem_list_get_count(list);

    snd_ctl_elem_list_alloc_space(list, cnt);
    snd_ctl_elem_list(ctl, list);

    //値取得

    snd_ctl_elem_info_malloc(&info);
    snd_ctl_elem_value_malloc(&value);

    for(i = 0; i < cnt; i++)
    {
        numid = snd_ctl_elem_list_get_numid(list, i);

        //情報
    
        snd_ctl_elem_info_set_numid(info, numid);
        snd_ctl_elem_info(ctl, info);

        printf("-- [%d] --\n", i);
        printf("<name> %s\n", snd_ctl_elem_list_get_name(list, i));

        tp = snd_ctl_elem_info_get_type(info);
        printf("type: (%d) %s\n", tp, snd_ctl_elem_type_name(tp));

        valcnt = snd_ctl_elem_info_get_count(info);

        //値

        snd_ctl_elem_value_set_numid(value, numid);
        snd_ctl_elem_read(ctl, value);

        switch(tp)
        {
            case SND_CTL_ELEM_TYPE_BOOLEAN:
                for(j = 0; j < valcnt; j++)
                    printf("%d, ", snd_ctl_elem_value_get_boolean(value, j));
                printf("\n");
                break;
            case SND_CTL_ELEM_TYPE_INTEGER:
                for(j = 0; j < valcnt; j++)
                    printf("%ld, ", snd_ctl_elem_value_get_integer(value, j));
                printf("\n");
                break;
            case SND_CTL_ELEM_TYPE_ENUMERATED:
                for(j = 0; j < valcnt; j++)
                    printf("%d, ", snd_ctl_elem_value_get_enumerated(value, j));
                printf("\n");
                break;
            case SND_CTL_ELEM_TYPE_BYTES:
                _put_bytes(NULL, snd_ctl_elem_value_get_bytes(value), valcnt);
                break;
            case SND_CTL_ELEM_TYPE_INTEGER64:
                for(j = 0; j < valcnt; j++)
                    printf("%lld, ", snd_ctl_elem_value_get_integer64(value, j));
                printf("\n");
                break;
            case SND_CTL_ELEM_TYPE_IEC958:
                snd_ctl_elem_value_get_iec958(value, &iec);

                _put_bytes("status", iec.status, 24);
                _put_bytes("subcode", iec.subcode, 147);
                _put_bytes("dig_subframe", iec.dig_subframe, 4);
                break;
        }
    }

    snd_ctl_elem_value_free(value);
    snd_ctl_elem_info_free(info);

    //

    snd_ctl_elem_list_free_space(list);
    snd_ctl_elem_list_free(list);

    snd_ctl_close(ctl);

    return 0;
}
実行結果
-- [0] --
<name> Channel Mode
type: (3) ENUMERATED
0, 
-- [1] --
<name> Front Playback Volume
type: (2) INTEGER
64, 64, 
-- [2] --
<name> Front Playback Switch
type: (1) BOOLEAN
0, 0, 
-- [3] --
<name> Surround Playback Volume
type: (2) INTEGER
0, 0, 

-- [34] --
<name> Front Headphone Jack
type: (1) BOOLEAN
1, 

-- [59] --
<name> PCM Playback Volume
type: (2) INTEGER
253, 253, 
-- [60] --
<name> Digital Capture Volume
type: (2) INTEGER
120, 120,

Volume は音量です。
整数値で、値が2つあります (左右のチャンネルごとの音量)。

Playback Switch は、ミュートの設定です。
値が2つある場合は、左右のチャンネルごとに変更できます。
0 でミュート、1 で非ミュートです。

Auto-Mute Mode は、端子が接続されたり外された時に、自動でミュートを ON/OFF にします。

Input Source は、録音時に、どの端子からデータを入力するかです。

〜Jack は、各端子が接続されているかです。