1c72fcc34Sopenharmony_ci/* 2c72fcc34Sopenharmony_ci * Advanced Linux Sound Architecture Control Program - General info 3c72fcc34Sopenharmony_ci * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 4c72fcc34Sopenharmony_ci * 5c72fcc34Sopenharmony_ci * 6c72fcc34Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 7c72fcc34Sopenharmony_ci * it under the terms of the GNU General Public License as published by 8c72fcc34Sopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 9c72fcc34Sopenharmony_ci * (at your option) any later version. 10c72fcc34Sopenharmony_ci * 11c72fcc34Sopenharmony_ci * This program is distributed in the hope that it will be useful, 12c72fcc34Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13c72fcc34Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14c72fcc34Sopenharmony_ci * GNU General Public License for more details. 15c72fcc34Sopenharmony_ci * 16c72fcc34Sopenharmony_ci * You should have received a copy of the GNU General Public License 17c72fcc34Sopenharmony_ci * along with this program; if not, write to the Free Software 18c72fcc34Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19c72fcc34Sopenharmony_ci * 20c72fcc34Sopenharmony_ci */ 21c72fcc34Sopenharmony_ci 22c72fcc34Sopenharmony_ci#include "aconfig.h" 23c72fcc34Sopenharmony_ci#include "alsactl.h" 24c72fcc34Sopenharmony_ci 25c72fcc34Sopenharmony_cistatic int pcm_device_list(snd_ctl_t *ctl, snd_pcm_stream_t stream, bool *first) 26c72fcc34Sopenharmony_ci{ 27c72fcc34Sopenharmony_ci#ifdef __ALSA_PCM_H 28c72fcc34Sopenharmony_ci int err, dev, idx; 29c72fcc34Sopenharmony_ci unsigned int count; 30c72fcc34Sopenharmony_ci snd_pcm_info_t *pcminfo; 31c72fcc34Sopenharmony_ci snd_pcm_info_alloca(&pcminfo); 32c72fcc34Sopenharmony_ci bool streamfirst, subfirst; 33c72fcc34Sopenharmony_ci 34c72fcc34Sopenharmony_ci dev = -1; 35c72fcc34Sopenharmony_ci streamfirst = true; 36c72fcc34Sopenharmony_ci while (1) { 37c72fcc34Sopenharmony_ci if ((err = snd_ctl_pcm_next_device(ctl, &dev)) < 0) { 38c72fcc34Sopenharmony_ci error("snd_ctl_pcm_next_device"); 39c72fcc34Sopenharmony_ci return err; 40c72fcc34Sopenharmony_ci } 41c72fcc34Sopenharmony_ci if (dev < 0) 42c72fcc34Sopenharmony_ci break; 43c72fcc34Sopenharmony_ci snd_pcm_info_set_device(pcminfo, dev); 44c72fcc34Sopenharmony_ci snd_pcm_info_set_subdevice(pcminfo, 0); 45c72fcc34Sopenharmony_ci snd_pcm_info_set_stream(pcminfo, stream); 46c72fcc34Sopenharmony_ci if ((err = snd_ctl_pcm_info(ctl, pcminfo)) < 0) { 47c72fcc34Sopenharmony_ci if (err != -ENOENT) 48c72fcc34Sopenharmony_ci return err; 49c72fcc34Sopenharmony_ci continue; 50c72fcc34Sopenharmony_ci } 51c72fcc34Sopenharmony_ci if (*first) { 52c72fcc34Sopenharmony_ci printf(" pcm:\n"); 53c72fcc34Sopenharmony_ci *first = false; 54c72fcc34Sopenharmony_ci } 55c72fcc34Sopenharmony_ci if (streamfirst) { 56c72fcc34Sopenharmony_ci printf(" - stream: %s\n devices:\n", snd_pcm_stream_name(stream)); 57c72fcc34Sopenharmony_ci streamfirst = false; 58c72fcc34Sopenharmony_ci } 59c72fcc34Sopenharmony_ci printf(" - device: %d\n id: %s\n name: %s\n", 60c72fcc34Sopenharmony_ci dev, 61c72fcc34Sopenharmony_ci snd_pcm_info_get_id(pcminfo), 62c72fcc34Sopenharmony_ci snd_pcm_info_get_name(pcminfo)); 63c72fcc34Sopenharmony_ci count = snd_pcm_info_get_subdevices_count(pcminfo); 64c72fcc34Sopenharmony_ci subfirst = true; 65c72fcc34Sopenharmony_ci for (idx = 0; idx < (int)count; idx++) { 66c72fcc34Sopenharmony_ci snd_pcm_info_set_subdevice(pcminfo, idx); 67c72fcc34Sopenharmony_ci if ((err = snd_ctl_pcm_info(ctl, pcminfo)) < 0) { 68c72fcc34Sopenharmony_ci error("control digital audio playback info (%s): %s", snd_ctl_name(ctl), snd_strerror(err)); 69c72fcc34Sopenharmony_ci return err; 70c72fcc34Sopenharmony_ci } 71c72fcc34Sopenharmony_ci if (subfirst) { 72c72fcc34Sopenharmony_ci printf(" subdevices:\n"); 73c72fcc34Sopenharmony_ci subfirst = false; 74c72fcc34Sopenharmony_ci } 75c72fcc34Sopenharmony_ci printf(" - subdevice: %d\n name: %s\n", 76c72fcc34Sopenharmony_ci idx, snd_pcm_info_get_subdevice_name(pcminfo)); 77c72fcc34Sopenharmony_ci } 78c72fcc34Sopenharmony_ci } 79c72fcc34Sopenharmony_ci#endif 80c72fcc34Sopenharmony_ci return 0; 81c72fcc34Sopenharmony_ci} 82c72fcc34Sopenharmony_ci 83c72fcc34Sopenharmony_cistatic const char *snd_rawmidi_stream_name(snd_rawmidi_stream_t stream) 84c72fcc34Sopenharmony_ci{ 85c72fcc34Sopenharmony_ci if (stream == SND_RAWMIDI_STREAM_INPUT) 86c72fcc34Sopenharmony_ci return "INPUT"; 87c72fcc34Sopenharmony_ci if (stream == SND_RAWMIDI_STREAM_OUTPUT) 88c72fcc34Sopenharmony_ci return "OUTPUT"; 89c72fcc34Sopenharmony_ci return "???"; 90c72fcc34Sopenharmony_ci} 91c72fcc34Sopenharmony_ci 92c72fcc34Sopenharmony_cistatic int rawmidi_device_list(snd_ctl_t *ctl, snd_rawmidi_stream_t stream, bool *first) 93c72fcc34Sopenharmony_ci{ 94c72fcc34Sopenharmony_ci#ifdef __ALSA_RAWMIDI_H 95c72fcc34Sopenharmony_ci int err, dev, idx; 96c72fcc34Sopenharmony_ci unsigned int count; 97c72fcc34Sopenharmony_ci snd_rawmidi_info_t *info; 98c72fcc34Sopenharmony_ci snd_rawmidi_info_alloca(&info); 99c72fcc34Sopenharmony_ci bool streamfirst, subfirst; 100c72fcc34Sopenharmony_ci 101c72fcc34Sopenharmony_ci dev = -1; 102c72fcc34Sopenharmony_ci streamfirst = true; 103c72fcc34Sopenharmony_ci while (1) { 104c72fcc34Sopenharmony_ci if ((err = snd_ctl_rawmidi_next_device(ctl, &dev)) < 0) { 105c72fcc34Sopenharmony_ci error("snd_ctl_rawmidi_next_device"); 106c72fcc34Sopenharmony_ci return err; 107c72fcc34Sopenharmony_ci } 108c72fcc34Sopenharmony_ci if (dev < 0) 109c72fcc34Sopenharmony_ci break; 110c72fcc34Sopenharmony_ci snd_rawmidi_info_set_device(info, dev); 111c72fcc34Sopenharmony_ci snd_rawmidi_info_set_subdevice(info, 0); 112c72fcc34Sopenharmony_ci snd_rawmidi_info_set_stream(info, stream); 113c72fcc34Sopenharmony_ci if ((err = snd_ctl_rawmidi_info(ctl, info)) < 0) { 114c72fcc34Sopenharmony_ci if (err != -ENOENT) 115c72fcc34Sopenharmony_ci return err; 116c72fcc34Sopenharmony_ci continue; 117c72fcc34Sopenharmony_ci } 118c72fcc34Sopenharmony_ci if (*first) { 119c72fcc34Sopenharmony_ci printf(" rawmidi:\n"); 120c72fcc34Sopenharmony_ci *first = false; 121c72fcc34Sopenharmony_ci } 122c72fcc34Sopenharmony_ci if (streamfirst) { 123c72fcc34Sopenharmony_ci printf(" - stream: %s\n devices:\n", snd_rawmidi_stream_name(stream)); 124c72fcc34Sopenharmony_ci streamfirst = false; 125c72fcc34Sopenharmony_ci } 126c72fcc34Sopenharmony_ci printf(" - device: %d\n id: %s\n name: %s\n", 127c72fcc34Sopenharmony_ci dev, 128c72fcc34Sopenharmony_ci snd_rawmidi_info_get_id(info), 129c72fcc34Sopenharmony_ci snd_rawmidi_info_get_name(info)); 130c72fcc34Sopenharmony_ci count = snd_rawmidi_info_get_subdevices_count(info); 131c72fcc34Sopenharmony_ci subfirst = true; 132c72fcc34Sopenharmony_ci for (idx = 0; idx < (int)count; idx++) { 133c72fcc34Sopenharmony_ci snd_rawmidi_info_set_subdevice(info, idx); 134c72fcc34Sopenharmony_ci if ((err = snd_ctl_rawmidi_info(ctl, info)) < 0) { 135c72fcc34Sopenharmony_ci error("control digital audio playback info (%s): %s", snd_ctl_name(ctl), snd_strerror(err)); 136c72fcc34Sopenharmony_ci return err; 137c72fcc34Sopenharmony_ci } 138c72fcc34Sopenharmony_ci if (subfirst) { 139c72fcc34Sopenharmony_ci printf(" subdevices:\n"); 140c72fcc34Sopenharmony_ci subfirst = false; 141c72fcc34Sopenharmony_ci } 142c72fcc34Sopenharmony_ci printf(" - subdevice: %d\n name: %s\n", 143c72fcc34Sopenharmony_ci idx, snd_rawmidi_info_get_subdevice_name(info)); 144c72fcc34Sopenharmony_ci } 145c72fcc34Sopenharmony_ci } 146c72fcc34Sopenharmony_ci#endif 147c72fcc34Sopenharmony_ci return 0; 148c72fcc34Sopenharmony_ci} 149c72fcc34Sopenharmony_ci 150c72fcc34Sopenharmony_cistatic int hwdep_device_list(snd_ctl_t *ctl) 151c72fcc34Sopenharmony_ci{ 152c72fcc34Sopenharmony_ci#ifdef __ALSA_HWDEP_H 153c72fcc34Sopenharmony_ci int err, dev; 154c72fcc34Sopenharmony_ci snd_hwdep_info_t *info; 155c72fcc34Sopenharmony_ci snd_hwdep_info_alloca(&info); 156c72fcc34Sopenharmony_ci bool first; 157c72fcc34Sopenharmony_ci 158c72fcc34Sopenharmony_ci dev = -1; 159c72fcc34Sopenharmony_ci first = true; 160c72fcc34Sopenharmony_ci while (1) { 161c72fcc34Sopenharmony_ci if ((err = snd_ctl_hwdep_next_device(ctl, &dev)) < 0) { 162c72fcc34Sopenharmony_ci error("snd_ctl_pcm_next_device"); 163c72fcc34Sopenharmony_ci return err; 164c72fcc34Sopenharmony_ci } 165c72fcc34Sopenharmony_ci if (dev < 0) 166c72fcc34Sopenharmony_ci break; 167c72fcc34Sopenharmony_ci snd_hwdep_info_set_device(info, dev); 168c72fcc34Sopenharmony_ci if ((err = snd_ctl_hwdep_info(ctl, info)) < 0) { 169c72fcc34Sopenharmony_ci if (err != -ENOENT) 170c72fcc34Sopenharmony_ci return err; 171c72fcc34Sopenharmony_ci continue; 172c72fcc34Sopenharmony_ci } 173c72fcc34Sopenharmony_ci if (first) { 174c72fcc34Sopenharmony_ci printf(" hwdep:\n"); 175c72fcc34Sopenharmony_ci first = false; 176c72fcc34Sopenharmony_ci } 177c72fcc34Sopenharmony_ci printf(" - device: %d\n id: %s\n name: %s\n iface: %d\n", 178c72fcc34Sopenharmony_ci dev, 179c72fcc34Sopenharmony_ci snd_hwdep_info_get_id(info), 180c72fcc34Sopenharmony_ci snd_hwdep_info_get_name(info), 181c72fcc34Sopenharmony_ci snd_hwdep_info_get_iface(info)); 182c72fcc34Sopenharmony_ci } 183c72fcc34Sopenharmony_ci#endif 184c72fcc34Sopenharmony_ci return 0; 185c72fcc34Sopenharmony_ci} 186c72fcc34Sopenharmony_ci 187c72fcc34Sopenharmony_cistatic int card_info(snd_ctl_t *ctl) 188c72fcc34Sopenharmony_ci{ 189c72fcc34Sopenharmony_ci snd_ctl_card_info_t *info; 190c72fcc34Sopenharmony_ci snd_ctl_elem_list_t *clist; 191c72fcc34Sopenharmony_ci int err; 192c72fcc34Sopenharmony_ci 193c72fcc34Sopenharmony_ci snd_ctl_card_info_alloca(&info); 194c72fcc34Sopenharmony_ci snd_ctl_elem_list_alloca(&clist); 195c72fcc34Sopenharmony_ci 196c72fcc34Sopenharmony_ci if ((err = snd_ctl_card_info(ctl, info)) < 0) { 197c72fcc34Sopenharmony_ci error("Control device %s hw info error: %s", snd_ctl_name(ctl), snd_strerror(err)); 198c72fcc34Sopenharmony_ci return err; 199c72fcc34Sopenharmony_ci } 200c72fcc34Sopenharmony_ci printf("#\n# Sound card\n#\n"); 201c72fcc34Sopenharmony_ci printf("- card: %i\n id: %s\n name: %s\n longname: %s\n", 202c72fcc34Sopenharmony_ci snd_ctl_card_info_get_card(info), 203c72fcc34Sopenharmony_ci snd_ctl_card_info_get_id(info), 204c72fcc34Sopenharmony_ci snd_ctl_card_info_get_name(info), 205c72fcc34Sopenharmony_ci snd_ctl_card_info_get_longname(info)); 206c72fcc34Sopenharmony_ci printf(" driver_name: %s\n", snd_ctl_card_info_get_driver(info)); 207c72fcc34Sopenharmony_ci printf(" mixer_name: %s\n", snd_ctl_card_info_get_mixername(info)); 208c72fcc34Sopenharmony_ci printf(" components: %s\n", snd_ctl_card_info_get_components(info)); 209c72fcc34Sopenharmony_ci if ((err = snd_ctl_elem_list(ctl, clist)) < 0) { 210c72fcc34Sopenharmony_ci error("snd_ctl_elem_list failure: %s", snd_strerror(err)); 211c72fcc34Sopenharmony_ci } else { 212c72fcc34Sopenharmony_ci printf(" controls_count: %i\n", snd_ctl_elem_list_get_count(clist)); 213c72fcc34Sopenharmony_ci } 214c72fcc34Sopenharmony_ci return err; 215c72fcc34Sopenharmony_ci} 216c72fcc34Sopenharmony_ci 217c72fcc34Sopenharmony_ciint general_card_info(int cardno) 218c72fcc34Sopenharmony_ci{ 219c72fcc34Sopenharmony_ci snd_ctl_t *ctl; 220c72fcc34Sopenharmony_ci char dev[16]; 221c72fcc34Sopenharmony_ci bool first; 222c72fcc34Sopenharmony_ci int err; 223c72fcc34Sopenharmony_ci 224c72fcc34Sopenharmony_ci snprintf(dev, sizeof(dev), "hw:%i", cardno); 225c72fcc34Sopenharmony_ci if ((err = snd_ctl_open(&ctl, dev, 0)) < 0) { 226c72fcc34Sopenharmony_ci error("Control device %s open error: %s", dev, snd_strerror(err)); 227c72fcc34Sopenharmony_ci return err; 228c72fcc34Sopenharmony_ci } 229c72fcc34Sopenharmony_ci err = card_info(ctl); 230c72fcc34Sopenharmony_ci 231c72fcc34Sopenharmony_ci first = true; 232c72fcc34Sopenharmony_ci if (err >= 0) 233c72fcc34Sopenharmony_ci err = pcm_device_list(ctl, SND_PCM_STREAM_PLAYBACK, &first); 234c72fcc34Sopenharmony_ci if (err >= 0) 235c72fcc34Sopenharmony_ci err = pcm_device_list(ctl, SND_PCM_STREAM_CAPTURE, &first); 236c72fcc34Sopenharmony_ci 237c72fcc34Sopenharmony_ci first = true; 238c72fcc34Sopenharmony_ci if (err >= 0) 239c72fcc34Sopenharmony_ci err = rawmidi_device_list(ctl, SND_RAWMIDI_STREAM_INPUT, &first); 240c72fcc34Sopenharmony_ci if (err >= 0) 241c72fcc34Sopenharmony_ci err = rawmidi_device_list(ctl, SND_RAWMIDI_STREAM_OUTPUT, &first); 242c72fcc34Sopenharmony_ci 243c72fcc34Sopenharmony_ci if (err >= 0) 244c72fcc34Sopenharmony_ci err = hwdep_device_list(ctl); 245c72fcc34Sopenharmony_ci snd_ctl_close(ctl); 246c72fcc34Sopenharmony_ci return err; 247c72fcc34Sopenharmony_ci} 248c72fcc34Sopenharmony_ci 249c72fcc34Sopenharmony_ciint general_info(const char *cardname) 250c72fcc34Sopenharmony_ci{ 251c72fcc34Sopenharmony_ci struct snd_card_iterator iter; 252c72fcc34Sopenharmony_ci int err; 253c72fcc34Sopenharmony_ci 254c72fcc34Sopenharmony_ci err = snd_card_iterator_sinit(&iter, cardname); 255c72fcc34Sopenharmony_ci if (err < 0) 256c72fcc34Sopenharmony_ci return err; 257c72fcc34Sopenharmony_ci while (snd_card_iterator_next(&iter)) { 258c72fcc34Sopenharmony_ci if ((err = general_card_info(iter.card))) 259c72fcc34Sopenharmony_ci return err; 260c72fcc34Sopenharmony_ci } 261c72fcc34Sopenharmony_ci return snd_card_iterator_error(&iter); 262c72fcc34Sopenharmony_ci} 263