snd_config_for_each(i, next, conf) { snd_config_t *n = snd_config_iterator_entry(i); const char *id; if (snd_config_get_id(n, &id) < 0) continue; if (strcmp(id, "comment") == 0) continue; if (strcmp(id, "type") == 0) continue; if (strcmp(id, "card") == 0) { err = snd_config_get_integer(n, &card); if (err < 0) { err = snd_config_get_string(n, &str); if (err < 0) return -EINVAL; card = snd_card_get_index(str); if (card < 0) return card; } continue; } if (strcmp(id, "device") == 0) { err = snd_config_get_integer(n, &device); if (err < 0) return err; continue; } SNDERR("Unexpected field %s", id); return -EINVAL; }
/* very simple device name parsing; only limited prefix are allowed: * "hw" and "default" */ int _snd_dev_get_device(const char *name, int *cardp, int *devp, int *subdevp) { int card; *cardp = 0; if (devp) *devp = 0; if (subdevp) *subdevp = -1; if (!strcmp(name, "hw") || !strcmp(name, "default") || !strcmp(name, "sysdefault")) return 0; if (!strncmp(name, "hw:", 3)) name += 3; else if (!strncmp(name, "default:", 8)) name += 8; else if (!strncmp(name, "sysdefault:", 11)) name += 11; else return -EINVAL; card = snd_card_get_index(name); if (card < 0) return card; *cardp = card; if (devp && subdevp) { /* parse the secondary and third arguments (if any) */ name = strchr(name, ','); if (name) { sscanf(name, ",%d,%d", devp, subdevp); if (*devp < 0 || *devp >= SALSA_MAX_DEVICES) return -EINVAL; } } return 0; }
mixerVolume::mixerVolume(const char *name, const char *card, long volume) { snd_mixer_selem_id_t *sid = NULL; elem = NULL; handle = NULL; min = 0; max = 100; char cardId[10]; if (!name || !card) return; int cx = snd_card_get_index(card); if (cx < 0 || cx > 31) return; snprintf(cardId, sizeof(cardId), "hw:%i", cx); if (0 > snd_mixer_open(&handle, 0)) return; if (0 > snd_mixer_attach(handle, cardId)) return; if (0 > snd_mixer_selem_register(handle, NULL, NULL)) return; if (0 > snd_mixer_load(handle)) return; snd_mixer_selem_id_alloca(&sid); if (!sid) return; snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, name); elem = snd_mixer_find_selem(handle, sid); if (elem) { snd_mixer_selem_get_playback_volume_range(elem, &min, &max); setVolume(volume); } }
static void amixer_card(t_amixer *x, t_symbol *s, int argc, t_atom *argv) { if(1==argc){ int id=-1; if(A_FLOAT==argv->a_type)id=atom_getint(argv); else id=snd_card_get_index(atom_getsymbol(argv)->s_name); if (id >= 0 && id < 32) sprintf(x->card, "hw:%i", id); else { pd_error(x, "invalid card %d", id); return; } } else error("amixer: can only be integer of symbol"); }
bool QAudioDeviceInfoInternal::open() { int err = 0; QString dev = device; if(!dev.contains(QLatin1String("default"))) { int idx = snd_card_get_index(dev.toLocal8Bit().constData()); dev = QString(QLatin1String("hw:%1,0")).arg(idx); } if(mode == QAudio::AudioOutput) { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); } else { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0); } if(err < 0) { handle = 0; return false; } return true; }
bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const { // Set nearest to closest settings that do work. // See if what is in settings will work (return value). int err = 0; snd_pcm_t* handle; snd_pcm_hw_params_t *params; QString dev = device; // open() if(!dev.contains(QLatin1String("default"))) { int idx = snd_card_get_index(dev.toLocal8Bit().constData()); dev = QString(QLatin1String("hw:%1,0")).arg(idx); } if(mode == QAudio::AudioOutput) { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); } else { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0); } if(err < 0) { handle = 0; return false; } bool testChannel = false; bool testCodec = false; bool testFreq = false; bool testType = false; bool testSize = false; int dir = 0; snd_pcm_nonblock( handle, 0 ); snd_pcm_hw_params_alloca( ¶ms ); snd_pcm_hw_params_any( handle, params ); // set the values! snd_pcm_hw_params_set_channels(handle,params,format.channels()); snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); switch(format.sampleSize()) { case 8: if(format.sampleType() == QAudioFormat::SignedInt) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8); else if(format.sampleType() == QAudioFormat::UnSignedInt) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8); break; case 16: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE); } break; case 32: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE); } } // For now, just accept only audio/pcm codec if(!format.codec().startsWith(QLatin1String("audio/pcm"))) { err=-1; } else testCodec = true; if(err>=0 && format.channels() != -1) { err = snd_pcm_hw_params_test_channels(handle,params,format.channels()); if(err>=0) err = snd_pcm_hw_params_set_channels(handle,params,format.channels()); if(err>=0) testChannel = true; } if(err>=0 && format.frequency() != -1) { err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0); if(err>=0) err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); if(err>=0) testFreq = true; } if((err>=0 && format.sampleSize() != -1) && (format.sampleType() != QAudioFormat::Unknown)) { switch(format.sampleSize()) { case 8: if(format.sampleType() == QAudioFormat::SignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8); else if(format.sampleType() == QAudioFormat::UnSignedInt) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8); break; case 16: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE); } break; case 32: if(format.sampleType() == QAudioFormat::SignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE); } else if(format.sampleType() == QAudioFormat::UnSignedInt) { if(format.byteOrder() == QAudioFormat::LittleEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE); else if(format.byteOrder() == QAudioFormat::BigEndian) err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE); } } if(err>=0) { testSize = true; testType = true; } } if(err>=0) err = snd_pcm_hw_params(handle, params); if(err == 0) { // settings work // close() if(handle) snd_pcm_close(handle); return true; } if(handle) snd_pcm_close(handle); return false; }
/** * \brief Parse control element id from the config * \param conf the config tree to parse * \param ctl_id the pointer to store the resultant control element id * \param cardp the pointer to store the card index * \param cchannelsp the pointer to store the number of channels (optional) * \param hwctlp the pointer to store the h/w control flag (optional) * \return 0 if successful, or a negative error code * * This function parses the given config tree to retrieve the control element id * and the card index. It's used by softvol. External PCM plugins can use this * function for creating or assigining their controls. * * cchannelsp and hwctlp arguments are optional. Set NULL if not necessary. */ int snd_pcm_parse_control_id(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp, int *cchannelsp, int *hwctlp) { snd_config_iterator_t i, next; int iface = SND_CTL_ELEM_IFACE_MIXER; const char *name = NULL; long index = 0; long device = -1; long subdevice = -1; int err; assert(ctl_id && cardp); *cardp = -1; if (cchannelsp) *cchannelsp = 2; snd_config_for_each(i, next, conf) { snd_config_t *n = snd_config_iterator_entry(i); const char *id; if (snd_config_get_id(n, &id) < 0) continue; if (strcmp(id, "comment") == 0) continue; if (strcmp(id, "card") == 0) { const char *str; long v; if ((err = snd_config_get_integer(n, &v)) < 0) { if ((err = snd_config_get_string(n, &str)) < 0) { SNDERR("Invalid field %s", id); goto _err; } *cardp = snd_card_get_index(str); if (*cardp < 0) { SNDERR("Cannot get index for %s", str); err = *cardp; goto _err; } } else *cardp = v; continue; } if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) { const char *ptr; if ((err = snd_config_get_string(n, &ptr)) < 0) { SNDERR("field %s is not a string", id); goto _err; } if ((err = snd_config_get_ctl_iface_ascii(ptr)) < 0) { SNDERR("Invalid value for '%s'", id); goto _err; } iface = err; continue; } if (strcmp(id, "name") == 0) { if ((err = snd_config_get_string(n, &name)) < 0) { SNDERR("field %s is not a string", id); goto _err; } continue; } if (strcmp(id, "index") == 0) { if ((err = snd_config_get_integer(n, &index)) < 0) { SNDERR("field %s is not an integer", id); goto _err; } continue; } if (strcmp(id, "device") == 0) { if ((err = snd_config_get_integer(n, &device)) < 0) { SNDERR("field %s is not an integer", id); goto _err; } continue; } if (strcmp(id, "subdevice") == 0) { if ((err = snd_config_get_integer(n, &subdevice)) < 0) { SNDERR("field %s is not an integer", id); goto _err; } continue; } if (cchannelsp && strcmp(id, "count") == 0) { long v; if ((err = snd_config_get_integer(n, &v)) < 0) { SNDERR("field %s is not an integer", id); goto _err; } if (v < 1 || v > 2) { SNDERR("Invalid count %ld", v); goto _err; } *cchannelsp = v; continue; } if (hwctlp && strcmp(id, "hwctl") == 0) { if ((err = snd_config_get_bool(n)) < 0) { SNDERR("The field %s must be a boolean type", id); return err; } *hwctlp = err; continue; } SNDERR("Unknown field %s", id); return -EINVAL; }