/** * Partly based on get_cards function in alsamixer. * This gets all alsa cards and fills the global * GSList 'cards'. * The list always starts with the 'default' card. */ static void get_cards(void) { int err, num; snd_ctl_card_info_t *info; snd_ctl_t *ctl; char buf[10]; struct acard *cur_card, *default_card; if (cards != NULL) g_slist_free_full(cards, card_free); cards = NULL; default_card = g_malloc(sizeof(struct acard)); default_card->name = g_strdup("(default)"); default_card->dev = g_strdup("default"); default_card->channels = get_channels("default"); cards = g_slist_append(cards, default_card); // don't need to free this as it's alloca'd snd_ctl_card_info_alloca(&info); num = -1; for (;;) { err = snd_card_next(&num); if (err < 0) { report_error("Can't get sounds cards: %s", snd_strerror(err)); return; } if (num < 0) break; sprintf(buf, "hw:%d", num); if (snd_ctl_open(&ctl, buf, 0) < 0) continue; err = snd_ctl_card_info(ctl, info); snd_ctl_close(ctl); if (err < 0) continue; cur_card = g_malloc(sizeof(struct acard)); cur_card->name = g_strdup(snd_ctl_card_info_get_name(info)); sprintf(buf, "hw:%d", num); cur_card->dev = g_strdup(buf); cur_card->channels = get_channels(buf); cards = g_slist_append(cards, cur_card); } #ifdef DEBUG GSList *tmp = cards; if (tmp) { printf("------ Card list ------\n"); while (tmp) { struct acard *c = tmp->data; printf("\t%s\t%s\t%s\n", c->dev, c->name, c->channels ? "" : "No chann"); tmp = tmp->next; } printf("-----------------------\n"); } #endif }
static int cards(lua_State *lstate) { snd_ctl_t *handle; int ret, card, ord; char buf[32]; snd_ctl_card_info_t *info; snd_ctl_card_info_alloca(&info); ord = 1; card = -1; lua_newtable(lstate); while (1) { if ((snd_card_next(&card) < 0) || (card < 0)) break; sprintf(buf, "hw:%d", card); if ((ret = snd_ctl_open(&handle, buf, 0)) < 0) { logmsg("control open: %s\n", snd_strerror(ret)); continue; } if ((ret = snd_ctl_card_info(handle, info)) < 0) { logmsg("control info: %s\n", snd_strerror(ret)); continue; } lua_pushinteger(lstate, ord++); lua_newtable(lstate); set_string(lstate, "dev", buf); set_string(lstate, "name", snd_ctl_card_info_get_name(info)); lua_settable(lstate, -3); snd_ctl_close(handle); //view_card(buf); } return 1; }
static PyObject * pyalsacontrol_cardinfo(struct pyalsacontrol *self, PyObject *args) { snd_ctl_card_info_t *info; PyObject *d; snd_ctl_card_info_alloca(&info); int err = snd_ctl_card_info(self->handle, info); if (err < 0) { PyErr_Format(PyExc_IOError, "Control card info error: %s", strerror(-err)); return NULL; } d = PyDict_New(); if (d) { PyDict_SetItem(d, PyString_FromString("card"), PyInt_FromLong(snd_ctl_card_info_get_card(info))); PyDict_SetItem(d, PyString_FromString("id"), PyString_FromString(snd_ctl_card_info_get_id(info))); PyDict_SetItem(d, PyString_FromString("driver"), PyString_FromString(snd_ctl_card_info_get_driver(info))); PyDict_SetItem(d, PyString_FromString("name"), PyString_FromString(snd_ctl_card_info_get_driver(info))); PyDict_SetItem(d, PyString_FromString("longname"), PyString_FromString(snd_ctl_card_info_get_longname(info))); PyDict_SetItem(d, PyString_FromString("mixername"), PyString_FromString(snd_ctl_card_info_get_mixername(info))); PyDict_SetItem(d, PyString_FromString("components"), PyString_FromString(snd_ctl_card_info_get_components(info))); } return d; }
static SCM alsa_cards(void) { // compile list of available cards int card; char buf[32]; char *pt; SCM list, alist; snd_ctl_card_info_t *info; snd_ctl_card_info_alloca(&info); card = -1; list = SCM_EOL; while (1) { if ((snd_card_next(&card) < 0) || (card < 0)) break; sprintf(buf, "hw:%d", card); alist = SCM_EOL; alist = scm_assq_set_x(alist, SYM("dev"), scm_from_locale_string(buf)); snd_card_get_name(card, &pt); alist = scm_assq_set_x(alist, SYM("name"), scm_take_locale_string(pt)); list = scm_cons(alist, list); scm_remember_upto_here_1(alist); } scm_remember_upto_here_1(list); return list; }
int main(int argc, char **argv) { register int err; int cardNum; // Start with first card cardNum = -1; for (;;) { snd_ctl_t *cardHandle; // Get next sound card's card number. When "cardNum" == -1, then ALSA // fetches the first card if ((err = snd_card_next(&cardNum)) < 0) { printf("Can't get the next card number: %s\n", snd_strerror(err)); break; } // No more cards? ALSA sets "cardNum" to -1 if so if (cardNum < 0) break; // Open this card's control interface. We specify only the card number -- not // any device nor sub-device too { char str[64]; sprintf(str, "hw:%i", cardNum); if ((err = snd_ctl_open(&cardHandle, str, 0)) < 0) { printf("Can't open card %i: %s\n", cardNum, snd_strerror(err)); continue; } } { snd_ctl_card_info_t *cardInfo; // We need to get a snd_ctl_card_info_t. Just alloc it on the stack snd_ctl_card_info_alloca(&cardInfo); // Tell ALSA to fill in our snd_ctl_card_info_t with info about this card if ((err = snd_ctl_card_info(cardHandle, cardInfo)) < 0) printf("Can't get info for card %i: %s\n", cardNum, snd_strerror(err)); else printf("Card %i = %s\n", cardNum, snd_ctl_card_info_get_name(cardInfo)); } // Close the card's control interface after we're done with it snd_ctl_close(cardHandle); } // ALSA allocates some mem to load its config file when we call some of the // above functions. Now that we're done getting the info, let's tell ALSA // to unload the info and free up that mem snd_config_update_free_global(); }
static char *ListAvailableDevices( demux_t *p_demux, bool b_probe ) { snd_ctl_card_info_t *p_info = NULL; snd_ctl_card_info_alloca( &p_info ); snd_pcm_info_t *p_pcminfo = NULL; snd_pcm_info_alloca( &p_pcminfo ); if( !b_probe ) msg_Dbg( p_demux, "Available alsa capture devices:" ); int i_card = -1; while( !snd_card_next( &i_card ) && i_card >= 0 ) { char psz_devname[10]; snprintf( psz_devname, 10, "hw:%d", i_card ); snd_ctl_t *p_ctl = NULL; if( snd_ctl_open( &p_ctl, psz_devname, 0 ) < 0 ) continue; snd_ctl_card_info( p_ctl, p_info ); if( !b_probe ) msg_Dbg( p_demux, " %s (%s)", snd_ctl_card_info_get_id( p_info ), snd_ctl_card_info_get_name( p_info ) ); int i_dev = -1; while( !snd_ctl_pcm_next_device( p_ctl, &i_dev ) && i_dev >= 0 ) { snd_pcm_info_set_device( p_pcminfo, i_dev ); snd_pcm_info_set_subdevice( p_pcminfo, 0 ); snd_pcm_info_set_stream( p_pcminfo, SND_PCM_STREAM_CAPTURE ); if( snd_ctl_pcm_info( p_ctl, p_pcminfo ) < 0 ) continue; if( !b_probe ) msg_Dbg( p_demux, " hw:%d,%d : %s (%s)", i_card, i_dev, snd_pcm_info_get_id( p_pcminfo ), snd_pcm_info_get_name( p_pcminfo ) ); else { char *psz_device; if( asprintf( &psz_device, "hw:%d,%d", i_card, i_dev ) > 0 ) { if( ProbeAudioDevAlsa( p_demux, psz_device ) ) { snd_ctl_close( p_ctl ); return psz_device; } else free( psz_device ); } } } snd_ctl_close( p_ctl ); } return NULL; }
bool MainWindowImpl::FindRadioshark(string& device) { int card = -1; int dev = -1; snd_ctl_t *handle = NULL; snd_ctl_card_info_t *info = NULL; snd_pcm_info_t *pcminfo = NULL; snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE; char card_id[32]; char *name = NULL; snd_ctl_card_info_alloca (&info); snd_pcm_info_alloca (&pcminfo); if (snd_card_next (&card) < 0 || card < 0) { return false; } while(card >= 0) { snprintf (card_id, 32, "hw:%d", card); if (snd_ctl_open (&handle, card_id, 0) == 0) { snd_ctl_card_info (handle, info); while (1) { snd_ctl_pcm_next_device (handle, &dev); if (dev < 0){ break; } snd_pcm_info_set_device (pcminfo, dev); snd_pcm_info_set_subdevice (pcminfo, 0); snd_pcm_info_set_stream (pcminfo, stream); if (snd_ctl_pcm_info (handle, pcminfo) >= 0) { snd_card_get_name (card, &name); if(strncmp(name,"radioSHARK",32) == 0) {void PokeScreensaver(void); snd_ctl_close(handle); free (name); snprintf (card_id, 32, "hw:%d,%d", card,dev); device = string(card_id); return true; } free (name); } } snd_ctl_close(handle); } snd_card_next (&card); } return false;//didn't find the proper Radioshark card. }
std::vector<HwIDPair> AlsaLayer::getAudioDeviceIndexMap(bool getCapture) const { snd_ctl_t* handle; snd_ctl_card_info_t *info; snd_pcm_info_t* pcminfo; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); int numCard = -1; std::vector<HwIDPair> audioDevice; if (snd_card_next(&numCard) < 0 || numCard < 0) return audioDevice; do { std::stringstream ss; ss << numCard; std::string name = "hw:" + ss.str(); if (snd_ctl_open(&handle, name.c_str(), 0) == 0) { if (snd_ctl_card_info(handle, info) == 0) { snd_pcm_info_set_device(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, getCapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK); int err; if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { WARN("Cannot get info for %s %s: %s", getCapture ? "capture device" : "playback device", name.c_str(), snd_strerror(err)); } else { DEBUG("card %i : %s [%s]", numCard, snd_ctl_card_info_get_id(info), snd_ctl_card_info_get_name(info)); std::string description = snd_ctl_card_info_get_name(info); description.append(" - "); description.append(snd_pcm_info_get_name(pcminfo)); // The number of the sound card is associated with a string description audioDevice.push_back(HwIDPair(numCard, description)); } } snd_ctl_close(handle); } } while (snd_card_next(&numCard) >= 0 && numCard >= 0); return audioDevice; }
/** * ags_devout_list_cards: * @soundcard: the #AgsSoundcard * @card_id: alsa identifier * @card_name: card name * * List available soundcards. * * Since: 0.4 */ void ags_devout_list_cards(AgsSoundcard *soundcard, GList **card_id, GList **card_name) { snd_ctl_t *card_handle; snd_ctl_card_info_t *card_info; char *name; gchar *str; int card_num; int error; *card_id = NULL; *card_name = NULL; card_num = -1; while(TRUE){ error = snd_card_next(&card_num); if(card_num < 0){ break; } if(error < 0){ continue; } str = g_strdup_printf("hw:%i\0", card_num); error = snd_ctl_open(&card_handle, str, 0); if(error < 0){ continue; } snd_ctl_card_info_alloca(&card_info); error = snd_ctl_card_info(card_handle, card_info); if(error < 0){ continue; } *card_id = g_list_prepend(*card_id, str); *card_name = g_list_prepend(*card_name, g_strdup(snd_ctl_card_info_get_name(card_info))); snd_ctl_close(card_handle); } snd_config_update_free_global(); *card_id = g_list_reverse(*card_id); *card_name = g_list_reverse(*card_name); }
const std::string AlsaWork::getCardName(int index) { const std::string card(AlsaDevice::formatCardName(index)); snd_ctl_t *ctl; int err = snd_ctl_open(&ctl, card.c_str(), SND_CTL_NONBLOCK); if (err < 0) { checkError(err); return std::string(); } snd_ctl_card_info_t *cardInfo; snd_ctl_card_info_alloca(&cardInfo); err = snd_ctl_card_info(ctl, cardInfo); if (err < 0) { checkError(err); return std::string(); } const std::string cardName = snd_ctl_card_info_get_name(cardInfo); checkError(snd_ctl_close(ctl)); return cardName; }
void list_cards(void) { snd_ctl_card_info_t *p_info = NULL; snd_ctl_card_info_alloca(&p_info); snd_pcm_info_t *p_pcminfo = NULL; snd_pcm_info_alloca(&p_pcminfo); printf("Availible alsa capture devices:\n"); int i_card = -1; while (!snd_card_next(&i_card) && i_card >= 0) { char devname[10]; snprintf( devname, 10, "hw:%d", i_card ); snd_ctl_t *p_ctl = NULL; if ( snd_ctl_open( &p_ctl, devname, 0 ) < 0) continue; snd_ctl_card_info( p_ctl, p_info); printf("\t%s (%s)\n", snd_ctl_card_info_get_id(p_info), snd_ctl_card_info_get_name(p_info)); int i_dev = -1; while (!snd_ctl_pcm_next_device(p_ctl, &i_dev) && i_dev >= 0) { snd_pcm_info_set_device(p_pcminfo, i_dev); snd_pcm_info_set_subdevice(p_pcminfo, 0); snd_pcm_info_set_stream(p_pcminfo, SND_PCM_STREAM_CAPTURE); if (snd_ctl_pcm_info(p_ctl, p_pcminfo) < 0) continue; printf("\t\thw:%d,%d : %s (%s)\n", i_card, i_dev, snd_pcm_info_get_id(p_pcminfo), snd_pcm_info_get_name(p_pcminfo)); } snd_ctl_close(p_ctl); } }
static void as_setup_card_combo (GtkWidget *combo , SoundParams *sparams) { int card; int i ; int err; snd_ctl_t *handle; snd_ctl_card_info_t *info; char name[32]; gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "- default"); snd_ctl_card_info_alloca(&info); sparams->firstcard = -1; card = -1; for( i = 0 ; ; i++ ){ if (snd_card_next(&card) < 0 || card < 0) { if ( i == 0 ) { msg_error(_("no soundcards found...")); } return; } if ( sparams->firstcard < 0 ) { sparams->firstcard = card; } sprintf(name, "hw:%d", card); if ((err = snd_ctl_open(&handle, name, 0)) < 0) { msg_error(_("control open (%i): %s"), card, snd_strerror(err)); continue; } if ((err = snd_ctl_card_info(handle, info)) < 0) { msg_error(_("control hardware info (%i): %s"), card, snd_strerror(err)); snd_ctl_close(handle); continue; } sprintf(name, "%d %s", card, snd_ctl_card_info_get_name(info) ); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), name ); snd_ctl_close(handle); } }
static int card_to_num(const char* device) { int err; char* ctl_name; snd_ctl_card_info_t *card_info; snd_ctl_t* ctl_handle; int i = -1; snd_ctl_card_info_alloca (&card_info); ctl_name = get_control_device_name(device); if (ctl_name == NULL) { jack_error("get_control_device_name() failed."); goto fail; } if ((err = snd_ctl_open (&ctl_handle, ctl_name, 0)) < 0) { jack_error ("control open \"%s\" (%s)", ctl_name, snd_strerror(err)); goto free; } if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) { jack_error ("control hardware info \"%s\" (%s)", device, snd_strerror (err)); goto close; } i = snd_ctl_card_info_get_card(card_info); close: snd_ctl_close(ctl_handle); free: free(ctl_name); fail: return i; }
void SoundPref::getHwList(int mode) { snd_ctl_t *handle; int card, err; //int dev; snd_ctl_card_info_t *info; //snd_pcm_info_t *pcminfo; snd_ctl_card_info_alloca(&info); //snd_pcm_info_alloca(&pcminfo); card = -1; if (snd_card_next(&card) < 0 || card < 0) { qDebug() << "no soundcards found ..."; return; } while (card >= 0) { QString hwName = QString("hw:%1").arg(card); if ((err = snd_ctl_open(&handle, strdup(hwName.toAscii().data()), 0)) < 0) { qDebug() << "Error while opening (" << card << "): " << card, snd_strerror(err); if (snd_card_next(&card) < 0) { // no more cards break; } else continue; } if ((err = snd_ctl_card_info(handle, info)) < 0) { qDebug() << "Error while getting hardware info (" << card << "):" << snd_strerror(err); snd_ctl_close(handle); if (snd_card_next(&card) < 0) { // no more cards break; } else continue; } /* dev = -1; int indx = 0; while (1) { if (snd_ctl_pcm_next_device(handle, &dev) < 0) qDebug() << "no devices found ..."; if (dev < 0) break; snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { if (err != -ENOENT) qDebug() << "error while getting digital audio info (" << card << "): " << snd_strerror(err); continue; } hwDeviceInfo *hw = new hwDeviceInfo; hw->hwName = hwName; hw->card = card; hw->cardName = snd_ctl_card_info_get_name(info); hw->device = dev; hw->deviceName = snd_pcm_info_get_name(pcminfo); hwList->append(hw); indx ++; // append to selection list (ui) QListWidgetItem *it = new QListWidgetItem(hw->fullName(), ui.devicesLst); it->setData(Qt::UserRole, QVariant(indx)); qDebug() << "inserting one card item"; } */ hwDeviceInfo *hw = new hwDeviceInfo; hw->card = card; hw->cardName = snd_ctl_card_info_get_name(info); hwList->insert(hwName, hw); QListWidgetItem *it = new QListWidgetItem(hw->cardName, ui.playbackDevicesLst); it->setData(Qt::UserRole, QVariant(hwName)); if (hwName == mixerCard) { // select this item if it is default it->setSelected(true); } snd_ctl_close(handle); if (snd_card_next(&card) < 0) { // no more cards break; } else continue; } //snd_pcm_info_free(pcminfo); //snd_ctl_card_info_free(info); }
static jack_driver_param_constraint_desc_t * enum_alsa_devices() { snd_ctl_t * handle; snd_ctl_card_info_t * info; snd_pcm_info_t * pcminfo_capture; snd_pcm_info_t * pcminfo_playback; int card_no = -1; char card_id[JACK_DRIVER_PARAM_STRING_MAX + 1]; char device_id[JACK_DRIVER_PARAM_STRING_MAX + 1]; char description[64]; int device_no; bool has_capture; bool has_playback; jack_driver_param_constraint_desc_t * constraint_ptr; uint32_t array_size = 0; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo_capture); snd_pcm_info_alloca(&pcminfo_playback); constraint_ptr = NULL; while(snd_card_next(&card_no) >= 0 && card_no >= 0) { snprintf(card_id, sizeof(card_id), "hw:%d", card_no); if (snd_ctl_open(&handle, card_id, 0) >= 0 && snd_ctl_card_info(handle, info) >= 0) { fill_device(&constraint_ptr, &array_size, card_id, snd_ctl_card_info_get_name(info)); device_no = -1; while (snd_ctl_pcm_next_device(handle, &device_no) >= 0 && device_no != -1) { snprintf(device_id, sizeof(device_id), "%s,%d", card_id, device_no); snd_pcm_info_set_device(pcminfo_capture, device_no); snd_pcm_info_set_subdevice(pcminfo_capture, 0); snd_pcm_info_set_stream(pcminfo_capture, SND_PCM_STREAM_CAPTURE); has_capture = snd_ctl_pcm_info(handle, pcminfo_capture) >= 0; snd_pcm_info_set_device(pcminfo_playback, device_no); snd_pcm_info_set_subdevice(pcminfo_playback, 0); snd_pcm_info_set_stream(pcminfo_playback, SND_PCM_STREAM_PLAYBACK); has_playback = snd_ctl_pcm_info(handle, pcminfo_playback) >= 0; if (has_capture && has_playback) { snprintf(description, sizeof(description),"%s (duplex)", snd_pcm_info_get_name(pcminfo_capture)); } else if (has_capture) { snprintf(description, sizeof(description),"%s (capture)", snd_pcm_info_get_name(pcminfo_capture)); } else if (has_playback) { snprintf(description, sizeof(description),"%s (playback)", snd_pcm_info_get_name(pcminfo_playback)); } else { continue; } fill_device(&constraint_ptr, &array_size, device_id, description); } snd_ctl_close(handle); } } return constraint_ptr; }
static int findSoundCards(char **cardname) { int idx, dev, err; snd_ctl_t *handle; snd_hctl_t *hctlhandle; snd_ctl_card_info_t *cardinfo; snd_pcm_info_t *pcminfo; char str[32]; snd_ctl_card_info_alloca(&cardinfo); snd_pcm_info_alloca(&pcminfo); snd_hctl_elem_t *elem; snd_ctl_elem_id_t *id; snd_ctl_elem_info_t *info; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_alloca(&info); idx = -1; while (1) { if ((err = snd_card_next(&idx)) < 0) { LOGE("Card next error: %s\n", snd_strerror(err)); break; } if (idx < 0) break; sprintf(str, "hw:CARD=%i", idx); if ((err = snd_ctl_open(&handle, str, 0)) < 0) { LOGE("Open error: %s\n", snd_strerror(err)); continue; } if ((err = snd_ctl_card_info(handle, cardinfo)) < 0) { LOGE("HW info error: %s\n", snd_strerror(err)); continue; } LOGD("Soundcard #%i:\n", idx + 1); LOGD(" card - %i\n", snd_ctl_card_info_get_card(cardinfo)); LOGD(" id - '%s'\n", snd_ctl_card_info_get_id(cardinfo)); LOGD(" driver - '%s'\n", snd_ctl_card_info_get_driver(cardinfo)); LOGD(" name - '%s'\n", snd_ctl_card_info_get_name(cardinfo)); LOGD(" longname - '%s'\n", snd_ctl_card_info_get_longname(cardinfo)); LOGD(" mixername - '%s'\n", snd_ctl_card_info_get_mixername(cardinfo)); LOGD(" components - '%s'\n", snd_ctl_card_info_get_components(cardinfo)); strcpy(cardname[idx], snd_ctl_card_info_get_name(cardinfo)); LOGD("\n\n-----get cart name and id: %s : %d",cardname[idx],idx); snd_ctl_close(handle); if ((err = snd_hctl_open(&hctlhandle, str, 0)) < 0) { LOGE("Control %s open error: %s", str, snd_strerror(err)); return err; } if ((err = snd_hctl_load(hctlhandle)) < 0) { LOGE("Control %s local error: %s\n", str, snd_strerror(err)); return err; } for (elem = snd_hctl_first_elem(hctlhandle); elem; elem = snd_hctl_elem_next(elem)) { if ((err = snd_hctl_elem_info(elem, info)) < 0) { LOGE("Control %s snd_hctl_elem_info error: %s\n", str, snd_strerror(err)); return err; } snd_hctl_elem_get_id(elem, id); show_control_id(id); } snd_hctl_close(hctlhandle); } snd_config_update_free_global(); return 0; }
int main() { int cardNumber = -1; int errNum; char *controlType; char deviceID[16]; // ------------------------------------------------------------------------ // ALSA control elements. // ------------------------------------------------------------------------ snd_ctl_t *ctl; // Simple control handle. snd_ctl_elem_id_t *id; // Simple control element id. snd_ctl_elem_value_t *control; // Simple control element value. snd_ctl_elem_type_t type; // Simple control element type. snd_ctl_elem_info_t *info; // Simple control element info container. snd_ctl_card_info_t *card; // Simple control card info container. snd_hctl_t *hctl; // High level control handle; snd_hctl_elem_t *elem; // High level control element handle. // ------------------------------------------------------------------------ // Initialise ALSA card and device types. // ------------------------------------------------------------------------ snd_ctl_card_info_alloca( &card ); snd_ctl_elem_value_alloca( &control ); snd_ctl_elem_id_alloca( &id ); snd_ctl_elem_info_alloca( &info ); // ------------------------------------------------------------------------ // Start card section. // ------------------------------------------------------------------------ // For each card. while (1) { // Find next card number. If < 0 then returns 1st card. errNum = snd_card_next( &cardNumber ); if (( errNum < 0 ) || ( cardNumber < 0 )) break; // Concatenate strings to get card's control interface. sprintf( deviceID, "hw:%i", cardNumber ); // Try to open card. if ( snd_ctl_open( &ctl, deviceID, 0 ) < 0 ) { printf( "Error opening card.\n" ); continue; } // Fill control card info element. if ( snd_ctl_card_info( ctl, card ) < 0 ) { printf( "Error getting card info.\n" ); continue; } // -------------------------------------------------------------------- // Print header block. // -------------------------------------------------------------------- printf( "\t+-----------------------------" ); printf( "-----------------------------+\n" ); printf( "\t| Card: %d - %-46s |", cardNumber, snd_ctl_card_info_get_name( card )); printf( "\n" ); printf( "\t+--------+------------" ); printf( "+------------------------------------+\n" ); printf( "\t| Device | Type " ); printf( "| Name |\n" ); printf( "\t+--------+------------" ); printf( "+------------------------------------+\n" ); // -------------------------------------------------------------------- // Start control section. // -------------------------------------------------------------------- // Open an empty high level control. if ( snd_hctl_open( &hctl, deviceID, 0 ) < 0 ) printf( "Error opening high level control.\n" ); // Load high level control element. if ( snd_hctl_load( hctl ) < 0 ) printf( "Error loading high level control.\n" ); // -------------------------------------------------------------------- // For each control element. // -------------------------------------------------------------------- for ( elem = snd_hctl_first_elem( hctl ); elem; elem = snd_hctl_elem_next( elem )) { // Get ID of high level control element. snd_hctl_elem_get_id( elem, id ); // ---------------------------------------------------------------- // Determine control type. // ---------------------------------------------------------------- if ( snd_hctl_elem_info( elem, info ) < 0 ) printf( "Can't get control information.\n" ); type = snd_ctl_elem_info_get_type( info ); switch ( type ) { case SND_CTL_ELEM_TYPE_NONE: controlType = "None"; break; case SND_CTL_ELEM_TYPE_BOOLEAN: controlType = "Boolean"; break; case SND_CTL_ELEM_TYPE_INTEGER: controlType = "Integer"; break; case SND_CTL_ELEM_TYPE_INTEGER64: controlType = "Integer64"; break; case SND_CTL_ELEM_TYPE_ENUMERATED: controlType = "Enumerated"; break; case SND_CTL_ELEM_TYPE_BYTES: controlType = "Bytes"; break; case SND_CTL_ELEM_TYPE_IEC958: controlType = "IEC958"; break; default: controlType = "Not Found"; break; } printf( "\t| %-6i | %-10s | %-34s |\n", snd_hctl_elem_get_numid( elem ), controlType, snd_hctl_elem_get_name( elem )); } printf( "\t+--------+------------" ); printf( "+------------------------------------+\n\n" ); // -------------------------------------------------------------------- // Tidy up. // -------------------------------------------------------------------- snd_hctl_close( hctl ); snd_ctl_close( ctl ); } return 0; }
static int find_hwdep_device(int *cardP, int *devP) { snd_ctl_t *ctl_handle; snd_ctl_card_info_t *card_info; snd_hwdep_info_t *hwdep_info; int card; int dev; int err; char card_id[32]; ctl_handle = NULL; snd_ctl_card_info_alloca(&card_info); snd_hwdep_info_alloca(&hwdep_info); for (card = 0; card < 7; card++) { *cardP = card; if (ctl_handle) { snd_ctl_close(ctl_handle); ctl_handle = NULL; } // Get control handle for selected card sprintf(card_id, "hw:%i", card); if ((err = snd_ctl_open(&ctl_handle, card_id, 0)) < 0) { fprintf(stderr, "control open (%s): %s", card_id, snd_strerror(err)); return -1; } // Read control hardware info from card if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) { fprintf(stderr, "control hardware info (%s): %s", card_id, snd_strerror(err)); continue; } //if (strcmp(snd_ctl_card_info_get_driver(card_info),"BT SCO (d)")) // continue; dev = -1; err = 1; while (1) { int if_type; if (snd_ctl_hwdep_next_device(ctl_handle, &dev) < 0) fprintf(stderr, "hwdep next device (%s): %s", card_id, snd_strerror(err)); if (dev < 0) break; snd_hwdep_info_set_device(hwdep_info, dev); if (snd_ctl_hwdep_info(ctl_handle, hwdep_info) < 0) { if (err != -ENOENT) fprintf(stderr, "control hwdep info (%s): %s", card_id, snd_strerror(err)); continue; } if_type = snd_hwdep_info_get_iface(hwdep_info); if (if_type == SNDRV_HWDEP_IFACE_BT_SCO || if_type==12) { snd_ctl_close(ctl_handle); *devP = dev; return 0; } } } if (ctl_handle) snd_ctl_close(ctl_handle); return -1; }
void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) { /* ensure that ALSA has been initialized */ if(!snd_config) snd_config_update(); snd_ctl_t *ctlhandle; snd_pcm_t *pcmhandle; snd_ctl_card_info_t *ctlinfo; snd_ctl_card_info_alloca(&ctlinfo); memset(ctlinfo, 0, snd_ctl_card_info_sizeof()); snd_pcm_hw_params_t *hwparams; snd_pcm_hw_params_alloca(&hwparams); memset(hwparams, 0, snd_pcm_hw_params_sizeof()); snd_pcm_info_t *pcminfo; snd_pcm_info_alloca(&pcminfo); memset(pcminfo, 0, snd_pcm_info_sizeof()); /* get the sound config */ snd_config_t *config; snd_config_copy(&config, snd_config); std::string strHwName; int n_cards = -1; while (snd_card_next(&n_cards) == 0 && n_cards != -1) { std::stringstream sstr; sstr << "hw:" << n_cards; std::string strHwName = sstr.str(); if (snd_ctl_open_lconf(&ctlhandle, strHwName.c_str(), 0, config) != 0) { CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Unable to open control for device %s", strHwName.c_str()); continue; } if (snd_ctl_card_info(ctlhandle, ctlinfo) != 0) { CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Unable to get card control info for device %s", strHwName.c_str()); snd_ctl_close(ctlhandle); continue; } snd_hctl_t *hctl; if (snd_hctl_open_ctl(&hctl, ctlhandle) != 0) hctl = NULL; snd_hctl_load(hctl); int pcm_index = 0; int iec958_index = 0; int hdmi_index = 0; int dev = -1; while (snd_ctl_pcm_next_device(ctlhandle, &dev) == 0 && dev != -1) { snd_pcm_info_set_device (pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0 ); snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK); if (snd_ctl_pcm_info(ctlhandle, pcminfo) < 0) { CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Skipping device %s,%d as it does not have PCM playback ability", strHwName.c_str(), dev); continue; } int dev_index; sstr.str(std::string()); CAEDeviceInfo info; std::string devname = snd_pcm_info_get_name(pcminfo); bool maybeHDMI = false; /* detect HDMI */ if (devname.find("HDMI") != std::string::npos) { info.m_deviceType = AE_DEVTYPE_HDMI; dev_index = hdmi_index++; sstr << "hdmi"; } else { /* detect IEC958 */ /* some HDMI devices (intel) report Digital for HDMI also */ if (devname.find("Digital") != std::string::npos) maybeHDMI = true; if (maybeHDMI || devname.find("IEC958" ) != std::string::npos) { info.m_deviceType = AE_DEVTYPE_IEC958; dev_index = iec958_index; /* dont increment, it might be HDMI */ sstr << "iec958"; } else { info.m_deviceType = AE_DEVTYPE_PCM; dev_index = pcm_index++; sstr << "hw"; } } /* build the driver string to pass to ALSA */ sstr << ":CARD=" << snd_ctl_card_info_get_id(ctlinfo) << ",DEV=" << dev_index; info.m_deviceName = sstr.str(); /* get the friendly display name*/ info.m_displayName = snd_ctl_card_info_get_name(ctlinfo); info.m_displayNameExtra = devname; /* open the device for testing */ int err = snd_pcm_open_lconf(&pcmhandle, info.m_deviceName.c_str(), SND_PCM_STREAM_PLAYBACK, 0, config); /* if open of possible IEC958 failed and it could be HDMI, try as HDMI */ if (err < 0 && maybeHDMI) { /* check for HDMI if it failed */ sstr.str(std::string()); dev_index = hdmi_index; sstr << "hdmi"; sstr << ":CARD=" << snd_ctl_card_info_get_id(ctlinfo) << ",DEV=" << dev_index; info.m_deviceName = sstr.str(); err = snd_pcm_open_lconf(&pcmhandle, info.m_deviceName.c_str(), SND_PCM_STREAM_PLAYBACK, 0, config); /* if it was valid, increment the index and set the type */ if (err >= 0) { ++hdmi_index; info.m_deviceType = AE_DEVTYPE_HDMI; } } /* if it's still IEC958, increment the index */ if (info.m_deviceType == AE_DEVTYPE_IEC958) ++iec958_index; /* final error check */ if (err < 0) { CLog::Log(LOGINFO, "CAESinkALSA::EnumerateDevicesEx - Unable to open %s for capability detection", strHwName.c_str()); continue; } /* see if we can get ELD for this device */ if (info.m_deviceType == AE_DEVTYPE_HDMI) { bool badHDMI = false; if (hctl && !GetELD(hctl, dev, info, badHDMI)) CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Unable to obtain ELD information for device %s, make sure you have ALSA >= 1.0.25", info.m_deviceName.c_str()); if (badHDMI) { CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Skipping HDMI device %s as it has no ELD data", info.m_deviceName.c_str()); continue; } } /* ensure we can get a playback configuration for the device */ if (snd_pcm_hw_params_any(pcmhandle, hwparams) < 0) { CLog::Log(LOGINFO, "CAESinkALSA::EnumerateDevicesEx - No playback configurations available for device %s", info.m_deviceName.c_str()); snd_pcm_close(pcmhandle); continue; } /* detect the available sample rates */ for (unsigned int *rate = ALSASampleRateList; *rate != 0; ++rate) if (snd_pcm_hw_params_test_rate(pcmhandle, hwparams, *rate, 0) >= 0) info.m_sampleRates.push_back(*rate); /* detect the channels available */ int channels = 0; for (int i = 1; i <= ALSA_MAX_CHANNELS; ++i) if (snd_pcm_hw_params_test_channels(pcmhandle, hwparams, i) >= 0) channels = i; CAEChannelInfo alsaChannels; for (int i = 0; i < channels; ++i) { if (!info.m_channels.HasChannel(ALSAChannelMap[i])) info.m_channels += ALSAChannelMap[i]; alsaChannels += ALSAChannelMap[i]; } /* remove the channels from m_channels that we cant use */ info.m_channels.ResolveChannels(alsaChannels); /* detect the PCM sample formats that are available */ for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1)) { if (AE_IS_RAW(i) || i == AE_FMT_MAX) continue; snd_pcm_format_t fmt = AEFormatToALSAFormat(i); if (fmt == SND_PCM_FORMAT_UNKNOWN) continue; if (snd_pcm_hw_params_test_format(pcmhandle, hwparams, fmt) >= 0) info.m_dataFormats.push_back(i); } snd_pcm_close(pcmhandle); list.push_back(info); } /* snd_hctl_close also closes ctlhandle */ if (hctl) snd_hctl_close(hctl); else snd_ctl_close(ctlhandle); } }
bool LapsusAlsaMixer::init() { int err; snd_ctl_t *ctl_handle; snd_ctl_card_info_t *hw_info; snd_ctl_card_info_alloca(&hw_info); if ((err = snd_ctl_open (&ctl_handle, "default", 0)) < 0) return false; if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0) return false; snd_ctl_close (ctl_handle); if ((err = snd_mixer_open (&_handle, 0)) < 0) return false; if ((err = snd_mixer_attach (_handle, "default")) < 0) return false; if ((err = snd_mixer_selem_register (_handle, 0, 0)) < 0) return false; if ((err = snd_mixer_load (_handle)) < 0) return false; // printf("Card name: '%s'\n", snd_ctl_card_info_get_name(hw_info)); // printf("Device name: '%s'\n", snd_ctl_card_info_get_mixername(hw_info)); snd_mixer_elem_t *elem; snd_mixer_selem_id_t *tmp_sid = 0; for (elem = snd_mixer_first_elem(_handle); elem; elem = snd_mixer_elem_next(elem)) { if (snd_mixer_selem_is_active(elem)) { if (!tmp_sid) tmp_sid = (snd_mixer_selem_id_t*) malloc(snd_mixer_selem_id_sizeof()); snd_mixer_selem_get_id(elem, tmp_sid); const char *name = snd_mixer_selem_id_get_name( tmp_sid ); if (!strcasecmp(name, "Headphone")) { if (sids[ID_HP]) delete sids[ID_HP]; sids[ID_HP] = new SIDInfo(_handle, tmp_sid); tmp_sid = 0; } else if (!strcasecmp(name, "Front")) { if (sids[ID_F]) delete sids[ID_F]; sids[ID_F] = new SIDInfo(_handle, tmp_sid); tmp_sid = 0; } else if (!strcasecmp(name, "Master")) { if (sids[ID_M]) delete sids[ID_M]; sids[ID_M] = new SIDInfo(_handle, tmp_sid); tmp_sid = 0; } } } if (tmp_sid) free(tmp_sid); bool foundAny = false; for (int i = 0; i < ID_LAST; ++i) { if (sids[i]) { if (sids[i]->hasMute) { foundAny = true; } if (sids[i]->hasVolume) { foundAny = true; long range = sids[i]->max - sids[i]->min; if (range > _globalMax) _globalMax = range; } } } if (_globalMax > INT_MAX) _globalMax = INT_MAX; if (!foundAny) return false; for (int i = 0; i < ID_LAST; ++i) { if (sids[i]) sids[i]->setGlobalMax(_globalMax); } if ((_count = snd_mixer_poll_descriptors_count(_handle)) < 0) return false; _fds = (struct pollfd*) calloc(_count, sizeof(struct pollfd)); if (!_fds) return false; if ((err = snd_mixer_poll_descriptors(_handle, _fds, _count)) < 0) return false; if (err != _count) return 0; _sns = new QSocketNotifier*[_count]; for ( int i = 0; i < _count; ++i ) { _sns[i] = new QSocketNotifier(_fds[i].fd, QSocketNotifier::Read); connect(_sns[i], SIGNAL(activated(int)), this, SLOT(alsaEvent())); } // To read our current parameters. Signals will be emited, but those signals // are not yet connected to anything - this method is called from constructor // only. getVolume(); mixerIsMuted(); return true; }
static jack_driver_param_constraint_desc_t * enum_alsa_devices() { snd_ctl_t * handle; snd_ctl_card_info_t * info; snd_pcm_info_t * pcminfo_capture; snd_pcm_info_t * pcminfo_playback; int card_no = -1; jack_driver_param_value_t card_id; jack_driver_param_value_t device_id; char description[64]; int device_no; bool has_capture; bool has_playback; jack_driver_param_constraint_desc_t * constraint_ptr; uint32_t array_size = 0; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo_capture); snd_pcm_info_alloca(&pcminfo_playback); constraint_ptr = NULL; while(snd_card_next(&card_no) >= 0 && card_no >= 0) { snprintf(card_id.str, sizeof(card_id.str), "hw:%d", card_no); if (snd_ctl_open(&handle, card_id.str, 0) >= 0 && snd_ctl_card_info(handle, info) >= 0) { snprintf(card_id.str, sizeof(card_id.str), "hw:%s", snd_ctl_card_info_get_id(info)); if (!jack_constraint_add_enum( &constraint_ptr, &array_size, &card_id, snd_ctl_card_info_get_name(info))) goto fail; device_no = -1; while (snd_ctl_pcm_next_device(handle, &device_no) >= 0 && device_no != -1) { snprintf(device_id.str, sizeof(device_id.str), "%s,%d", card_id.str, device_no); snd_pcm_info_set_device(pcminfo_capture, device_no); snd_pcm_info_set_subdevice(pcminfo_capture, 0); snd_pcm_info_set_stream(pcminfo_capture, SND_PCM_STREAM_CAPTURE); has_capture = snd_ctl_pcm_info(handle, pcminfo_capture) >= 0; snd_pcm_info_set_device(pcminfo_playback, device_no); snd_pcm_info_set_subdevice(pcminfo_playback, 0); snd_pcm_info_set_stream(pcminfo_playback, SND_PCM_STREAM_PLAYBACK); has_playback = snd_ctl_pcm_info(handle, pcminfo_playback) >= 0; if (has_capture && has_playback) { snprintf(description, sizeof(description),"%s (duplex)", snd_pcm_info_get_name(pcminfo_capture)); } else if (has_capture) { snprintf(description, sizeof(description),"%s (capture)", snd_pcm_info_get_name(pcminfo_capture)); } else if (has_playback) { snprintf(description, sizeof(description),"%s (playback)", snd_pcm_info_get_name(pcminfo_playback)); } else { continue; } if (!jack_constraint_add_enum( &constraint_ptr, &array_size, &device_id, description)) goto fail; } snd_ctl_close(handle); } } return constraint_ptr; fail: jack_constraint_free(constraint_ptr); return NULL; }
void AudioALSA::list_devices(ArrayList<char*> *devices, int pcm_title, int mode) { snd_ctl_t *handle; int card, err, dev, idx; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; char string[BCTEXTLEN]; snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; int error; switch(mode) { case MODERECORD: stream = SND_PCM_STREAM_CAPTURE; break; case MODEPLAY: stream = SND_PCM_STREAM_PLAYBACK; break; } snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); card = -1; #define DEFAULT_DEVICE "default" char *result = new char[strlen(DEFAULT_DEVICE) + 1]; devices->append(result); devices->set_array_delete(); // since we are allocating by new[] strcpy(result, DEFAULT_DEVICE); while(snd_card_next(&card) >= 0) { char name[BCTEXTLEN]; if(card < 0) break; sprintf(name, "hw:%i", card); if((err = snd_ctl_open(&handle, name, 0)) < 0) { printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err)); continue; } if((err = snd_ctl_card_info(handle, info)) < 0) { printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err)); snd_ctl_close(handle); continue; } dev = -1; while(1) { unsigned int count; if(snd_ctl_pcm_next_device(handle, &dev) < 0) printf("AudioALSA::list_devices: snd_ctl_pcm_next_device\n"); if (dev < 0) break; snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, stream); if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { if(err != -ENOENT) printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err)); continue; } if(pcm_title) { sprintf(string, "plughw:%d,%d", card, dev); // strcpy(string, "cards.pcm.front"); } else { sprintf(string, "%s #%d", snd_ctl_card_info_get_name(info), dev); } char *result = devices->append(new char[strlen(string) + 1]); strcpy(result, string); } snd_ctl_close(handle); } // snd_ctl_card_info_free(info); // snd_pcm_info_free(pcminfo); }
void qjackctlInterfaceComboBox::populateModel (void) { bool bBlockSignals = QComboBox::blockSignals(true); QComboBox::setUpdatesEnabled(false); QComboBox::setDuplicatesEnabled(false); QLineEdit *pLineEdit = QComboBox::lineEdit(); // FIXME: Only valid for ALSA, Sun and OSS devices, // for the time being... and also CoreAudio ones too. const QString& sDriver = m_pDriverComboBox->currentText(); bool bAlsa = (sDriver == "alsa"); bool bSun = (sDriver == "sun"); bool bOss = (sDriver == "oss"); #ifdef CONFIG_COREAUDIO bool bCoreaudio = (sDriver == "coreaudio"); std::map<QString, AudioDeviceID> coreaudioIdMap; #endif #ifdef CONFIG_PORTAUDIO bool bPortaudio = (sDriver == "portaudio"); #endif QString sCurName = pLineEdit->text(); QString sName, sSubName; int iCards = 0; clearCards(); int iCurCard = -1; if (bAlsa) { #ifdef CONFIG_ALSA_SEQ // Enumerate the ALSA cards and PCM harfware devices... snd_ctl_t *handle; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); const QString sPrefix("hw:%1"); const QString sSuffix(" (%1)"); const QString sSubSuffix("%1,%2"); QString sName2, sSubName2; bool bCapture, bPlayback; int iCard = -1; while (snd_card_next(&iCard) >= 0 && iCard >= 0) { sName = sPrefix.arg(iCard); if (snd_ctl_open(&handle, sName.toUtf8().constData(), 0) >= 0 && snd_ctl_card_info(handle, info) >= 0) { sName2 = sPrefix.arg(snd_ctl_card_info_get_id(info)); addCard(sName2, snd_ctl_card_info_get_name(info) + sSuffix.arg(sName)); if (sCurName == sName || sCurName == sName2) iCurCard = iCards; ++iCards; int iDevice = -1; while (snd_ctl_pcm_next_device(handle, &iDevice) >= 0 && iDevice >= 0) { // Capture devices.. bCapture = false; if (m_iAudio == QJACKCTL_CAPTURE || m_iAudio == QJACKCTL_DUPLEX) { snd_pcm_info_set_device(pcminfo, iDevice); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); bCapture = (snd_ctl_pcm_info(handle, pcminfo) >= 0); } // Playback devices.. bPlayback = false; if (m_iAudio == QJACKCTL_PLAYBACK || m_iAudio == QJACKCTL_DUPLEX) { snd_pcm_info_set_device(pcminfo, iDevice); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); bPlayback = (snd_ctl_pcm_info(handle, pcminfo) >= 0); } // List iif compliant with the audio mode criteria... if ((m_iAudio == QJACKCTL_CAPTURE && bCapture && !bPlayback) || (m_iAudio == QJACKCTL_PLAYBACK && !bCapture && bPlayback) || (m_iAudio == QJACKCTL_DUPLEX && bCapture && bPlayback)) { sSubName = sSubSuffix.arg(sName).arg(iDevice); sSubName2 = sSubSuffix.arg(sName2).arg(iDevice); addCard(sSubName2, snd_pcm_info_get_name(pcminfo) + sSuffix.arg(sSubName)); if (sCurName == sSubName || sCurName == sSubName2) iCurCard = iCards; ++iCards; } } snd_ctl_close(handle); } } #endif // CONFIG_ALSA_SEQ } else if (bSun) { QFile file("/var/run/dmesg.boot"); if (file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); QString sLine; QRegExp rxDevice("audio([0-9]) at (.*)"); while (!stream.atEnd()) { sLine = stream.readLine(); if (rxDevice.exactMatch(sLine)) { sName = "/dev/audio" + rxDevice.cap(1); addCard(sName, rxDevice.cap(2)); if (sCurName == sName) iCurCard = iCards; ++iCards; } } file.close(); } } else if (bOss) { // Enumerate the OSS Audio devices... QFile file("/dev/sndstat"); if (file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); QString sLine; bool bAudioDevices = false; QRegExp rxHeader("Audio devices.*", Qt::CaseInsensitive); QRegExp rxDevice("([0-9]+):[ ]+(.*)"); while (!stream.atEnd()) { sLine = stream.readLine(); if (bAudioDevices) { if (rxDevice.exactMatch(sLine)) { sName = "/dev/dsp" + rxDevice.cap(1); addCard(sName, rxDevice.cap(2)); if (sCurName == sName) iCurCard = iCards; ++iCards; } else break; } else if (rxHeader.exactMatch(sLine)) bAudioDevices = true; } file.close(); } } #ifdef CONFIG_COREAUDIO else if (bCoreaudio) { // Find out how many Core Audio devices are there, if any... // (code snippet gently "borrowed" from Stephane Letz jackdmp;) OSStatus err; Boolean isWritable; UInt32 outSize = sizeof(isWritable); err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &outSize, &isWritable); if (err == noErr) { // Calculate the number of device available... int numCoreDevices = outSize / sizeof(AudioDeviceID); // Make space for the devices we are about to get... AudioDeviceID *coreDeviceIDs = new AudioDeviceID [numCoreDevices]; err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &outSize, (void *) coreDeviceIDs); if (err == noErr) { // Look for the CoreAudio device name... char coreDeviceName[256]; UInt32 nameSize = 256; for (int i = 0; i < numCoreDevices; i++) { err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], 0, true, kAudioDevicePropertyDeviceName, &outSize, &isWritable); if (err == noErr) { err = AudioDeviceGetProperty(coreDeviceIDs[i], 0, true, kAudioDevicePropertyDeviceName, &nameSize, (void *) coreDeviceName); if (err == noErr) { char drivername[128]; UInt32 dnsize = 128; // this returns the unique id for the device // that must be used on the commandline for jack if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, dnsize) == noErr) { sName = drivername; } else { sName = "Error"; } coreaudioIdMap[sName] = coreDeviceIDs[i]; // TODO: hide this ugly ID from the user, // only show human readable name // humanreadable \t UID sSubName = QString(coreDeviceName); addCard(sSubName, sName); if (sCurName == sName || sCurName == sSubName) iCurCard = iCards; ++iCards; } } } } delete [] coreDeviceIDs; } } #endif // CONFIG_COREAUDIO #ifdef CONFIG_PORTAUDIO else if (bPortaudio) { if (Pa_Initialize() == paNoError) { // Fill hostapi info... PaHostApiIndex iNumHostApi = Pa_GetHostApiCount(); QString *pHostName = new QString[iNumHostApi]; for (PaHostApiIndex i = 0; i < iNumHostApi; ++i) pHostName[i] = QString(Pa_GetHostApiInfo(i)->name); // Fill device info... PaDeviceIndex iNumDevice = Pa_GetDeviceCount(); PaDeviceInfo **ppDeviceInfo = new PaDeviceInfo * [iNumDevice]; for (PaDeviceIndex i = 0; i < iNumDevice; ++i) { ppDeviceInfo[i] = const_cast<PaDeviceInfo *> (Pa_GetDeviceInfo(i)); sName = pHostName[ppDeviceInfo[i]->hostApi] + "::" + QString(ppDeviceInfo[i]->name); addCard(sName, QString()); if (sCurName == sName) iCurCard = iCards; ++iCards; } Pa_Terminate(); } } #endif // CONFIG_PORTAUDIO addCard(m_sDefName, QString()); if (sCurName == m_sDefName || sCurName.isEmpty()) iCurCard = iCards; ++iCards; QTreeView *pTreeView = static_cast<QTreeView *> (QComboBox::view()); pTreeView->setMinimumWidth( pTreeView->sizeHint().width() + QComboBox::iconSize().width()); QComboBox::setCurrentIndex(iCurCard); pLineEdit->setText(sCurName); QComboBox::setUpdatesEnabled(true); QComboBox::blockSignals(bBlockSignals); }
void ManglerAlsa::getDeviceList(std::vector<ManglerAudioDevice*>& inputDevices, std::vector<ManglerAudioDevice*>& outputDevices) {/*{{{*/ snd_pcm_stream_t stream[2] = { SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE }; int ctr; for (ctr = 0; ctr < 2; ctr++) { // the rest is just copypasta, with bad code from alsa snd_ctl_t *handle; int card, err, dev, idx_p = 0, idx_c = 0; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; card = -1; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); if (snd_card_next(&card) < 0 || card < 0) { fputs("alsa: no sound cards found!\n", stderr); return; } while (card >= 0) { char hw[256] = ""; snprintf(hw, 255, "hw:%i", card); if ((err = snd_ctl_open(&handle, hw, 0)) < 0) { fprintf(stderr, "alsa: control open (%i): %s\n", card, snd_strerror(err)); if (snd_card_next(&card) < 0) { fprintf(stderr, "alsa: snd_ctl_open: snd_card_next\n"); break; } continue; } if ((err = snd_ctl_card_info(handle, info)) < 0) { fprintf(stderr, "alsa: control hardware info (%i): %s\n", card, snd_strerror(err)); snd_ctl_close(handle); if (snd_card_next(&card) < 0) { fprintf(stderr, "alsa: snd_ctl_card_info: snd_card_next\n"); break; } continue; } dev = -1; for (;;) { if (snd_ctl_pcm_next_device(handle, &dev) < 0) { fprintf(stderr, "alsa: snd_ctl_pcm_next_device\n"); } if (dev < 0) { break; } snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, stream[ctr]); if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { if (err != -ENOENT) { fprintf(stderr, "alsa: control digital audio info (%i): %s\n", card, snd_strerror(err)); } continue; } char name[256] = "", desc[512] = ""; snprintf(name, 255, "hw:%i,%i", card, dev); snprintf(desc, 511, "%s: %s (%s)", snd_ctl_card_info_get_name(info), snd_pcm_info_get_name(pcminfo), name ); switch (stream[ctr]) { case SND_PCM_STREAM_PLAYBACK: outputDevices.push_back( new ManglerAudioDevice( idx_p++, name, desc) ); break; case SND_PCM_STREAM_CAPTURE: inputDevices.push_back( new ManglerAudioDevice( idx_c++, name, desc) ); break; } } snd_ctl_close(handle); if (snd_card_next(&card) < 0) { fprintf(stderr, "alsa: snd_card_next\n"); break; } } } }/*}}}*/
static void device_list(snd_pcm_stream_t stream) { snd_ctl_t *handle; int card, err, dev, idx; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); card = -1; if (snd_card_next(&card) < 0 || card < 0) { error(_("no soundcards found...")); return; } printf(_("**** List of %s Hardware Devices ****\n"), snd_pcm_stream_name(stream)); while (card >= 0) { char name[32]; sprintf(name, "hw:%d", card); if ((err = snd_ctl_open(&handle, name, 0)) < 0) { error("control open (%i): %s", card, snd_strerror(err)); goto next_card; } if ((err = snd_ctl_card_info(handle, info)) < 0) { error("control hardware info (%i): %s", card, snd_strerror(err)); snd_ctl_close(handle); goto next_card; } dev = -1; while (1) { unsigned int count; if (snd_ctl_pcm_next_device(handle, &dev)<0) error("snd_ctl_pcm_next_device"); if (dev < 0) break; snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, stream); if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { if (err != -ENOENT) error("control digital audio info (%i): %s", card, snd_strerror(err)); continue; } printf(_("card %i: [%s,%i] %s [%s], device %i: %s [%s]\n"), card, name, dev, snd_ctl_card_info_get_id(info), snd_ctl_card_info_get_name(info), dev, snd_pcm_info_get_id(pcminfo), snd_pcm_info_get_name(pcminfo)); count = snd_pcm_info_get_subdevices_count(pcminfo); printf( _(" Subdevices: %i/%i\n"), snd_pcm_info_get_subdevices_avail(pcminfo), count); for (idx = 0; idx < (int)count; idx++) { snd_pcm_info_set_subdevice(pcminfo, idx); if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { error("control digital audio playback info (%i): %s", card, snd_strerror(err)); } else { printf(_(" Subdevice #%i: %s\n"), idx, snd_pcm_info_get_subdevice_name(pcminfo)); } } } snd_ctl_close(handle); next_card: if (snd_card_next(&card) < 0) { error("snd_card_next"); break; } } }
void asound_setup(const gchar * card, const gchar * channel, void (*volume_changed)(int,gboolean)) { gchar * card_override = NULL; // used to hold a string like hw:0 if a nice // device name was given as 'card' // Clean up resources from previous calls to setup g_free(m_channel); m_channel = NULL; if(m_elem) { snd_mixer_elem_set_callback(m_elem, NULL); m_elem = NULL; } if(m_mixer) { snd_mixer_close(m_mixer); m_mixer = NULL; } g_list_free_full(m_channel_names, g_free); m_channel_names = NULL; g_list_free_full(m_device_names, g_free); m_device_names = NULL; // Save card, volume_changed g_free(m_device); m_device = g_strdup(card); m_volume_changed = volume_changed; // Populate list of device names int card_number = -1; int ret = snd_card_next(&card_number); snd_ctl_card_info_t * info = NULL; snd_ctl_card_info_alloca(&info); m_device_names = g_list_append(m_device_names, (gpointer)g_strdup("default")); while(ret == 0 && card_number != -1) { char buf[16]; sprintf(buf, "hw:%d", card_number); snd_ctl_t * ctl = NULL; if(snd_ctl_open(&ctl, buf, 0) < 0) { continue; } if(snd_ctl_card_info(ctl, info) < 0) { snd_ctl_close(ctl); continue; } snd_ctl_close(ctl); gchar * nice_name = g_strdup(snd_ctl_card_info_get_name(info)); m_device_names = g_list_append(m_device_names, (gpointer)nice_name); if(g_strcmp0(nice_name, m_device) == 0) { g_free(card_override); card_override = g_strdup_printf("hw:%d", card_number); } ret = snd_card_next(&card_number); } // Load the mixer for the provided cardname snd_mixer_open(&m_mixer, 0); if(snd_mixer_attach(m_mixer, (card_override != NULL ? card_override : m_device)) < 0) { fprintf(stderr, "Failed to open sound device with name: %s\n", (card_override != NULL ? card_override : m_device)); snd_mixer_close(m_mixer); m_mixer = NULL; g_free(card_override); return; } else { g_free(card_override); } snd_mixer_selem_register(m_mixer, NULL, NULL); snd_mixer_load(m_mixer); // Setup g_io_watch for the mixer int count = snd_mixer_poll_descriptors_count(m_mixer); if(count >= 1) { struct pollfd pfd; count = snd_mixer_poll_descriptors(m_mixer, &pfd, 1); if(count == 1) { GIOChannel * giochannel = g_io_channel_unix_new(pfd.fd); g_io_add_watch_full(giochannel, G_PRIORITY_DEFAULT, G_IO_IN | G_IO_ERR , asound_poll_cb, NULL, NULL); } } // Iterate over the elements in the mixer and store them in m_channel_names int elemcount = snd_mixer_get_count(m_mixer); snd_mixer_elem_t * elem = snd_mixer_first_elem(m_mixer); int loop; for(loop = 0; loop < elemcount; loop++) { const char * elemname = snd_mixer_selem_get_name(elem); if(snd_mixer_selem_has_playback_volume(elem)) { m_channel_names = g_list_append(m_channel_names, (gpointer)g_strdup(elemname)); } elem = snd_mixer_elem_next(elem); } // Setup m_elem using the provided channelname if(channel != NULL && asound_channel_exists(channel)) asound_set_channel(channel); else if(m_channel_names != NULL) asound_set_channel((const gchar*)m_channel_names->data); }
static int get_controls(int cardno, snd_config_t *top) { snd_ctl_t *handle; snd_ctl_card_info_t *info; snd_config_t *state, *card, *control; snd_ctl_elem_list_t *list; unsigned int idx; int err; char name[32]; unsigned int count; const char *id; snd_ctl_card_info_alloca(&info); snd_ctl_elem_list_alloca(&list); sprintf(name, "hw:%d", cardno); err = snd_ctl_open(&handle, name, SND_CTL_READONLY); if (err < 0) { error("snd_ctl_open error: %s", snd_strerror(err)); return err; } err = snd_ctl_card_info(handle, info); if (err < 0) { error("snd_ctl_card_info error: %s", snd_strerror(err)); goto _close; } id = snd_ctl_card_info_get_id(info); err = snd_config_search(top, "state", &state); if (err == 0 && snd_config_get_type(state) != SND_CONFIG_TYPE_COMPOUND) { error("config state node is not a compound"); err = -EINVAL; goto _close; } if (err < 0) { err = snd_config_compound_add(top, "state", 1, &state); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); goto _close; } } err = snd_config_search(state, id, &card); if (err == 0 && snd_config_get_type(card) != SND_CONFIG_TYPE_COMPOUND) { error("config state.%s node is not a compound", id); err = -EINVAL; goto _close; } if (err < 0) { err = snd_config_compound_add(state, id, 0, &card); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); goto _close; } } err = snd_config_search(card, "control", &control); if (err == 0) { err = snd_config_delete(control); if (err < 0) { error("snd_config_delete: %s", snd_strerror(err)); goto _close; } } err = snd_ctl_elem_list(handle, list); if (err < 0) { error("Cannot determine controls: %s", snd_strerror(err)); goto _close; } count = snd_ctl_elem_list_get_count(list); err = snd_config_compound_add(card, "control", count > 0, &control); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); goto _close; } if (count == 0) { err = 0; goto _close; } snd_ctl_elem_list_set_offset(list, 0); if (snd_ctl_elem_list_alloc_space(list, count) < 0) { error("No enough memory..."); goto _close; } if ((err = snd_ctl_elem_list(handle, list)) < 0) { error("Cannot determine controls (2): %s", snd_strerror(err)); goto _free; } for (idx = 0; idx < count; ++idx) { snd_ctl_elem_id_t *id; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_list_get_id(list, idx, id); err = get_control(handle, id, control); if (err < 0) goto _free; } err = 0; _free: snd_ctl_elem_list_free_space(list); _close: snd_ctl_close(handle); return err; }
void AlsaBackend::UpdateDevicesList() { Log("AlsaBackend::UpdateDeviceList\n"); DeviceInfo info; void **hints, **n; char *name, *descr, *desc; unsigned devices = 0; InitDevicesList(); info.SetDevice(devices++, "default", "Default device", "default"); info.type = DeviceInfo::TYPE_PLUG; info.direction = 0; PcmPreProbe(info, OUTPUT); PcmPreProbe(info, INPUT); devicesList.push_back(info); // Start with safe alsa detection, list the devices from software config. snd_config_update(); if (snd_device_name_hint(-1, "pcm", &hints) < 0) return; n = hints; while (*n != NULL) { name = snd_device_name_get_hint(*n, "NAME"); descr = snd_device_name_get_hint(*n, "DESC"); if (!descr) desc = (char*)""; else { desc = descr; for (int i = strlen(desc); i > 0; i--) if (desc[i-1] == '\n') desc[i-1] = ' '; } if (IgnorePlugin(name)) { Log("Ignoring ALSA device %s", name); } else { info.SetDevice(devices++, name, desc, name); info.type = DeviceInfo::TYPE_PLUG; info.probed = false; info.direction = 0; PcmPreProbe(info, OUTPUT); PcmPreProbe(info, INPUT); if (info.direction != 0) devicesList.push_back(info); } if (name != NULL) free(name); if (descr != NULL) free(descr); n++; } snd_device_name_free_hint(hints); // Continue with new detection, this is a more thorough test with probing device characteristics enum { IDLEN = 12 }; char hwdev[IDLEN+1]; int card, err, dev; snd_ctl_t* handle = NULL; snd_ctl_card_info_t* cardinfo; snd_pcm_info_t* pcminfo; snd_ctl_card_info_alloca(&cardinfo); snd_pcm_info_alloca(&pcminfo); card = -1; while (snd_card_next(&card) == 0 && card >= 0) { snprintf(hwdev, IDLEN, "hw:%d", card); err = snd_ctl_open(&handle, hwdev, 0); if (sc_errcheck(err, "opening control interface", card, -1)) continue; err = snd_ctl_card_info(handle, cardinfo); if (sc_errcheck(err, "obtaining card info", card, -1)) { snd_ctl_close(handle); continue; } Log("Card %d, ID '%s', name '%s'", card, snd_ctl_card_info_get_id(cardinfo), snd_ctl_card_info_get_name(cardinfo)); dev = -1; if (snd_ctl_pcm_next_device(handle, &dev) < 0) { snd_ctl_close(handle); continue; } while (dev >= 0) { if (!DevProbe(handle, pcminfo, card, dev, OUTPUT) && !DevProbe(handle, pcminfo, card, dev, INPUT)) { if (snd_ctl_pcm_next_device(handle, &dev) < 0) break; } snprintf(hwdev, IDLEN, "hw:%d,%d", card, dev); char strbuf[DEVICE_NAME_MAXLEN]; snprintf(strbuf, DEVICE_NAME_MAXLEN, "%s, %s", snd_ctl_card_info_get_name(cardinfo), snd_pcm_info_get_name(pcminfo)); info.SetDevice(devices++, hwdev, strbuf, hwdev); info.type = DeviceInfo::TYPE_HW; info.probed = false; info.direction = 0; PcmPreProbe(info, OUTPUT); PcmPreProbe(info, INPUT); Log("**********\n%s :: %s\n**********\n", info.guid, info.displayName); devicesList.push_back(info); if (snd_ctl_pcm_next_device(handle, &dev) < 0) break; } snd_ctl_close(handle); } // And complement with chewing a bit on user-defined entries, too. // from PortAudio /* Iterate over plugin devices */ snd_config_t *topNode = NULL; assert(snd_config); if ((err = snd_config_search(snd_config, "pcm", &topNode)) >= 0) { snd_config_iterator_t i, next; snd_config_for_each(i, next, topNode) { const char *tpStr = "unknown", *idStr = NULL; int err = 0; snd_config_t *n = snd_config_iterator_entry(i), *tp = NULL; if ((err = snd_config_search(n, "type", &tp)) < 0) { if (-ENOENT != err) { Log("plugin list error: %s", snd_strerror(err)); } } else { snd_config_get_string(tp, &tpStr); } snd_config_get_id(n, &idStr); if (IgnorePlugin(idStr)) { Log("Ignoring ALSA plugin device %s of type %s", idStr, tpStr); continue; } Log("Found plugin %s of type %s", idStr, tpStr); info.SetDevice(devices++, idStr, idStr, tpStr); info.probed = false; info.direction = 0; if (strncmp(tpStr, "bluetooth", 9)==0) info.type = DeviceInfo::TYPE_BLUETOOTH; else if(strncmp(tpStr, "null", 4) == 0) { info.type = DeviceInfo::TYPE_NULL; // Never need to probe the null device. info.probed = true; } else if(strncmp(tpStr, "unknown", 4) == 0) info.type = DeviceInfo::TYPE_UNKNOWN; else { info.type = DeviceInfo::TYPE_PLUG; // No need to preprobe bluetooth, null and unknown(?) types. PcmPreProbe(info, OUTPUT); PcmPreProbe(info, INPUT); } devicesList.push_back(info); } }