alsactl 0.8.0

API binding for alsactl library
Documentation
// SPDX-License-Identifier: MIT
use alsactl::{prelude::*, *};

fn elem_iface_type_to_str(elem_iface_type: &ElemIfaceType) -> &str {
    match elem_iface_type {
        ElemIfaceType::Card => "Card",
        ElemIfaceType::Hwdep => "Hwdep",
        ElemIfaceType::Mixer => "Mixer",
        ElemIfaceType::Pcm => "Pcm",
        ElemIfaceType::Rawmidi => "Rawmidi",
        ElemIfaceType::Timer => "Timer",
        ElemIfaceType::Sequencer => "Sequencer",
        _ => "Unknown",
    }
}

fn elem_type_to_str(elem_type: &ElemType) -> &str {
    match elem_type {
        ElemType::None => "None",
        ElemType::Boolean => "Boolean",
        ElemType::Integer => "Integer",
        ElemType::Enumerated => "Enumerated",
        ElemType::Bytes => "Bytes",
        ElemType::Iec60958 => "Iec60958",
        ElemType::Integer64 => "Integer64",
        _ => "Unknown",
    }
}

fn dump_elem_data(card: &alsactl::Card, elem_id: &alsactl::ElemId) -> Result<(), glib::Error> {
    println!("Element {}:", elem_id.numid());
    println!("  device_id:      {}", elem_id.device_id());
    println!("  subdevice_id:   {}", elem_id.subdevice_id());
    println!("  name :          {}", elem_id.name());
    println!(
        "  iface:          {}",
        elem_iface_type_to_str(&elem_id.iface())
    );
    println!("  index:          {}", elem_id.index());

    let elem_info = card.elem_info(elem_id)?;

    let (elem_access, elem_owner, elem_type) = match &elem_info {
        ElemInfo::Iec60958(info) => (info.access(), info.owner(), info.elem_type()),
        ElemInfo::Boolean(info) => (info.access(), info.owner(), info.elem_type()),
        ElemInfo::Bytes(info) => (info.access(), info.owner(), info.elem_type()),
        ElemInfo::Integer(info) => (info.access(), info.owner(), info.elem_type()),
        ElemInfo::Integer64(info) => (info.access(), info.owner(), info.elem_type()),
        ElemInfo::Enumerated(info) => (info.access(), info.owner(), info.elem_type()),
    };
    println!("  access:         {:?}", elem_access);
    println!("  owner:          {}", elem_owner);
    println!("  type:           {}", elem_type_to_str(&elem_type));

    let value_count = match &elem_info {
        ElemInfo::Iec60958(_) => 0,
        ElemInfo::Boolean(info) => info.value_count(),
        ElemInfo::Bytes(info) => info.value_count(),
        ElemInfo::Integer(info) => info.value_count(),
        ElemInfo::Integer64(info) => info.value_count(),
        ElemInfo::Enumerated(info) => info.value_count(),
    };
    if value_count > 0 {
        println!("  value-count:    {}", value_count);
    }

    match &elem_info {
        ElemInfo::Integer(info) => {
            println!("    min:          {}", info.value_min());
            println!("    max:          {}", info.value_max());
            println!("    step:         {}", info.value_step());
        }
        ElemInfo::Integer64(info) => {
            println!("    min:          {}", info.value_min());
            println!("    max:          {}", info.value_max());
            println!("    step:         {}", info.value_step());
        }
        ElemInfo::Enumerated(info) => {
            info.labels().iter().enumerate().for_each(|(i, label)| {
                println!("    {}:       {}", i, label);
            });
        }
        _ => (),
    }

    let mut elem_value = ElemValue::new();
    card.read_elem_value(elem_id, &mut elem_value)?;

    match &elem_info {
        ElemInfo::Iec60958(_) => {
            println!(
                "  channel_status: {:?}",
                elem_value.iec60958_channel_status()
            );
            println!("  user_data:      {:?}", elem_value.iec60958_user_data());
        }
        ElemInfo::Boolean(info) => {
            let value_count = info.value_count() as usize;
            println!(
                "  values:         {:?}",
                &elem_value.boolean()[..value_count]
            );
        }
        ElemInfo::Bytes(info) => {
            let value_count = info.value_count() as usize;
            println!("  values:         {:?}", &elem_value.bytes()[..value_count]);
        }
        ElemInfo::Integer(info) => {
            let value_count = info.value_count() as usize;
            println!("  values:         {:?}", &elem_value.int()[..value_count]);
        }
        ElemInfo::Integer64(info) => {
            let value_count = info.value_count() as usize;
            println!("  values:         {:?}", &elem_value.int64()[..value_count]);
        }
        ElemInfo::Enumerated(info) => {
            let labels = info.labels();
            let value_count = info.value_count() as usize;
            let vals: Vec<_> = elem_value
                .enumerated()
                .iter()
                .take(value_count)
                .map(|&val| &labels[val as usize])
                .collect();
            println!("  values:         {:?}", vals);
        }
    }

    if elem_access.contains(ElemAccessFlag::TLV_READ) {
        let mut cntr = vec![0; 64];
        card.read_elem_tlv(elem_id, &mut cntr)?;
        println!("  tlv:            {:?}", cntr);
    }

    Ok(())
}

fn main() {
    let card_id_list = match alsactl::card_id_list() {
        Ok(entries) => entries,
        Err(_) => {
            eprintln!("Fail to get the list of sound card.");
            std::process::exit(1);
        }
    };

    card_id_list.iter().for_each(|&card_id| {
        let card = Card::new();
        if card.open(card_id, 0).is_err() {
            eprintln!("Fail to open sound card: {}", card_id);
            std::process::exit(1);
        }

        let elem_id_list = match card.elem_id_list() {
            Ok(entries) => entries,
            Err(_) => {
                eprintln!("Fail to get the list of element for sound card {}", card_id);
                std::process::exit(1);
            }
        };

        elem_id_list.iter().for_each(|elem_id| {
            if dump_elem_data(&card, elem_id).is_err() {
                eprintln!("Fail to dump the data of element: {}", elem_id.name());
                std::process::exit(1);
            }
        });
    });
}