void ipga_volume_update(int idx) { snd_ctl_elem_value_t *val; int err, ipga_vol; snd_ctl_elem_value_alloca(&val); snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_value_set_name(val, IPGA_VOLUME_NAME); snd_ctl_elem_value_set_index(val, idx); if ((err = snd_ctl_elem_read(ctl, val)) < 0) { g_print("Unable to read ipga volume: %s\n", snd_strerror(err)); return; } gtk_adjustment_set_value(GTK_ADJUSTMENT(av_ipga_volume_adj[idx]), -(ipga_vol = snd_ctl_elem_value_get_integer(val, 0))); snd_ctl_elem_value_set_name(val, ADC_VOLUME_NAME); snd_ctl_elem_value_set_index(val, idx); if ((err = snd_ctl_elem_read(ctl, val)) < 0) { g_print("Unable to read adc volume: %s\n", snd_strerror(err)); return; } // set ADC volume to max if IPGA volume greater 0 if (ipga_vol) gtk_adjustment_set_value(GTK_ADJUSTMENT(av_adc_volume_adj[idx]), -adc_max); }
int put_infos(int vol_min, int vol_max, snd_hctl_elem_t *volume_elem, snd_hctl_elem_t *mute_elem, snd_ctl_elem_value_t *volume_ctl, snd_ctl_elem_value_t *mute_ctl, char *format) { int volume; int volume_percent; bool mute_switch; char switch_state[4]; snd_hctl_elem_read(volume_elem, volume_ctl); snd_hctl_elem_read(mute_elem, mute_ctl); volume = (int)snd_ctl_elem_value_get_integer(volume_ctl, 0); mute_switch = (bool)snd_ctl_elem_value_get_boolean(mute_ctl, 0); volume_percent = (int)(100.0f * ((float)volume - vol_min) / (vol_max - vol_min)); if (mute_switch == true) sprintf(switch_state, "on"); else sprintf(switch_state, "off"); if (strstr(format, "%s") == NULL) printf(format, volume_percent); else if (strstr(format, "%i") == NULL) printf(format, switch_state); else printf(format, switch_state, volume_percent); printf("\n"); fflush(stdout); return EXIT_SUCCESS; }
long phoneui_utils_sound_volume_raw_get(enum SoundControlType type) { int err; long value; unsigned int i,count; snd_ctl_elem_value_t *control; snd_ctl_elem_value_alloca(&control); snd_hctl_elem_t *elem; count = controls[STATE_INDEX][type].count; elem = controls[STATE_INDEX][type].element; if (!elem || !count) { return 0; } err = snd_hctl_elem_read(elem, control); if (err < 0) { g_warning("%s", snd_strerror(err)); return -1; } value = 0; /* FIXME: possible long overflow */ for (i = 0 ; i < count ; i++) { value += snd_ctl_elem_value_get_integer(control, i); } value /= count; return value; }
static void change_int_elem_members(struct elem_set_trial *trial, snd_ctl_elem_value_t *elem_data) { long val; unsigned int i; for (i = 0; i < trial->member_count; ++i) { val = snd_ctl_elem_value_get_integer(elem_data, i); snd_ctl_elem_value_set_integer(elem_data, i, ++val); } }
int get_gain(int idx, int src, int dst) { int err; int val = HDSPMM_ERROR_NO_CARD; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *ctl; snd_ctl_t *handle; if(idx >= HDSPMM_MAX_CARDS || idx < 0) return HDSPMM_ERROR_WRONG_IDX; snd_ctl_elem_value_alloca(&ctl); snd_ctl_elem_id_alloca(&id); snd_ctl_elem_id_set_name(id, "Mixer"); snd_ctl_elem_id_set_numid(id, 0); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_HWDEP); snd_ctl_elem_id_set_device(id, 0); snd_ctl_elem_id_set_subdevice(id, 0); snd_ctl_elem_id_set_index(id, 0); snd_ctl_elem_value_set_id(ctl, id); if ((err = snd_ctl_open(&handle, card_name[cardid], SND_CTL_NONBLOCK)) < 0) { #ifndef QUIET fprintf(stderr, "Alsa error: %s\n", snd_strerror(err)); #endif return HDSPMM_ERROR_ALSA_OPEN; } snd_ctl_elem_value_set_integer(ctl, 0, src); snd_ctl_elem_value_set_integer(ctl, 1, dst); if ((err = snd_ctl_elem_read(handle, ctl)) < 0) { #ifndef QUIET fprintf(stderr, "Alsa error: %s\n", snd_strerror(err)); #endif return HDSPMM_ERROR_ALSA_READ; } val = snd_ctl_elem_value_get_integer(ctl, 2); snd_ctl_close(handle); return val; SETFLOAT(x->x_at+1, delta); SETFLOAT(x->x_at+2, phi); outlet_list(x->x_out_para, &s_list, 3, x->x_at); outlet_anything(x->x_obj.ob_outlet, s, x->x_size2d+1, x->x_at); }
/* NPM: changed for https://bugzilla.redhat.com/show_bug.cgi?id=602903 */ static void get_levels(int idx, int *l1, int *l2) { *l1 = *l2 = 0; if (idx == 0) { /* "if (stereo)" -- special case idx=0 as digital mix pair */ if ((peak_changed[IDX_LMIX] != RESET) && (peak_changed[IDX_RMIX] != RESET)) { /* don't change values if doing "Reset Peaks" */ if ((*l1 = snd_ctl_elem_value_get_integer(peaks, IDX_LMIX)) > peak_levels[IDX_LMIX]) { peak_levels[IDX_LMIX] = (*l1); peak_changed[IDX_LMIX] = TRUE; } if ((*l2 = snd_ctl_elem_value_get_integer(peaks, IDX_RMIX)) > peak_levels[IDX_RMIX]) { peak_levels[IDX_RMIX] = (*l2); peak_changed[IDX_RMIX] = TRUE; } } } else { if (peak_changed[idx-1] != RESET) { if ((*l1 = snd_ctl_elem_value_get_integer(peaks, idx - 1)) > peak_levels[idx - 1]) { peak_levels[idx - 1] = (*l1); peak_changed[idx - 1] = TRUE; } } } }
void dac_volume_update(int idx) { snd_ctl_elem_value_t *val; int err; snd_ctl_elem_value_alloca(&val); snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_value_set_name(val, DAC_VOLUME_NAME); snd_ctl_elem_value_set_index(val, idx); if ((err = snd_ctl_elem_read(ctl, val)) < 0) { g_print("Unable to read dac volume: %s\n", snd_strerror(err)); return; } gtk_adjustment_set_value(GTK_ADJUSTMENT(av_dac_volume_adj[idx]), -snd_ctl_elem_value_get_integer(val, 0)); }
static int elem_read_volume(selem_none_t *s, int dir, selem_ctl_type_t type) { snd_ctl_elem_value_t *ctl; unsigned int idx; int err; selem_ctl_t *c = &s->ctls[type]; snd_ctl_elem_value_alloca(&ctl); if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0) return err; for (idx = 0; idx < s->str[dir].channels; idx++) { unsigned int idx1 = idx; if (idx >= c->values) idx1 = 0; s->str[dir].vol[idx] = to_user(s, dir, c, snd_ctl_elem_value_get_integer(ctl, idx1)); } return 0; }
int set_gain(int idx, int src, int dst, int val) { int err; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *ctl; snd_ctl_t *handle; if(idx >= HDSPMM_MAX_CARDS || idx < 0) return HDSPMM_ERROR_WRONG_IDX; snd_ctl_elem_value_alloca(&ctl); snd_ctl_elem_id_alloca(&id); snd_ctl_elem_id_set_name(id, "Mixer"); snd_ctl_elem_id_set_numid(id, 0); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_HWDEP); snd_ctl_elem_id_set_device(id, 0); snd_ctl_elem_id_set_subdevice(id, 0); snd_ctl_elem_id_set_index(id, 0); snd_ctl_elem_value_set_id(ctl, id); if ((err = snd_ctl_open(&handle, card_name[idx], SND_CTL_NONBLOCK)) < 0) { #ifndef QUIET fprintf(stderr, "Alsa error: %s\n", snd_strerror(err)); #endif return HDSPMM_ERROR_ALSA_OPEN; } snd_ctl_elem_value_set_integer(ctl, 0, src); snd_ctl_elem_value_set_integer(ctl, 1, dst); snd_ctl_elem_value_set_integer(ctl, 2, val); if ((err = snd_ctl_elem_write(handle, ctl)) < 0) { #ifndef QUIET fprintf(stderr, "Alsa error: %s\n", snd_strerror(err)); #endif return HDSPMM_ERROR_ALSA_WRITE; } val = snd_ctl_elem_value_get_integer(ctl, 2); snd_ctl_close(handle); return val; }
static int elem_read_route(selem_none_t *s, int dir, selem_ctl_type_t type) { snd_ctl_elem_value_t *ctl; unsigned int idx; int err; selem_ctl_t *c = &s->ctls[type]; snd_ctl_elem_value_alloca(&ctl); if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0) return err; for (idx = 0; idx < s->str[dir].channels; idx++) { unsigned int idx1 = idx; if (idx >= c->values) idx1 = 0; if (!snd_ctl_elem_value_get_integer(ctl, idx1 * c->values + idx1)) s->str[dir].sw &= ~(1 << idx); } return 0; }
int V4LRadioControl::vol(snd_hctl_elem_t *elem) const { const QString card("hw:0"); int err; snd_ctl_elem_id_t *id; snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *control; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_alloca(&info); snd_ctl_elem_value_alloca(&control); if ((err = snd_hctl_elem_info(elem, info)) < 0) { return 0; } snd_hctl_elem_get_id(elem, id); snd_hctl_elem_read(elem, control); return snd_ctl_elem_value_get_integer(control, 0); }
status_t ALSAControl::get(const char *name, unsigned int &value, int index) { if (!mHandle) { ALOGE("Control not initialized"); return NO_INIT; } snd_ctl_elem_id_t *id; snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *control; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_alloca(&info); snd_ctl_elem_value_alloca(&control); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_id_set_name(id, name); snd_ctl_elem_info_set_id(info, id); int ret = snd_ctl_elem_info(mHandle, info); if (ret < 0) { ALOGE("Control '%s' cannot get element info: %d", name, ret); return BAD_VALUE; } int count = snd_ctl_elem_info_get_count(info); if (index >= count) { ALOGE("Control '%s' index is out of range (%d >= %d)", name, index, count); return BAD_VALUE; } snd_ctl_elem_info_get_id(info, id); snd_ctl_elem_value_set_id(control, id); ret = snd_ctl_elem_read(mHandle, control); if (ret < 0) { ALOGE("Control '%s' cannot read element value: %d", name, ret); return BAD_VALUE; } snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(info); switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: value = snd_ctl_elem_value_get_boolean(control, index); break; case SND_CTL_ELEM_TYPE_INTEGER: value = snd_ctl_elem_value_get_integer(control, index); break; case SND_CTL_ELEM_TYPE_INTEGER64: value = snd_ctl_elem_value_get_integer64(control, index); break; case SND_CTL_ELEM_TYPE_ENUMERATED: value = snd_ctl_elem_value_get_enumerated(control, index); break; case SND_CTL_ELEM_TYPE_BYTES: value = snd_ctl_elem_value_get_byte(control, index); break; default: return BAD_VALUE; } return NO_ERROR; }
static int show_control(const char* card, const char *space, snd_hctl_elem_t *elem, int level) { int err; unsigned int item, idx; unsigned int count; snd_ctl_elem_type_t type; snd_ctl_elem_id_t *id; snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *control; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_alloca(&info); snd_ctl_elem_value_alloca(&control); if ((err = snd_hctl_elem_info(elem, info)) < 0) { error("Control %s snd_hctl_elem_info error: %s\n", card, snd_strerror(err)); return err; } if (level & LEVEL_ID) { snd_hctl_elem_get_id(elem, id); show_control_id(id); printf("\n"); } count = snd_ctl_elem_info_get_count(info); type = snd_ctl_elem_info_get_type(info); printf("%s; type=%s,access=%s,values=%i", space, control_type(info), control_access(info), count); switch (type) { case SND_CTL_ELEM_TYPE_INTEGER: printf(",min=%li,max=%li,step=%li\n", snd_ctl_elem_info_get_min(info), snd_ctl_elem_info_get_max(info), snd_ctl_elem_info_get_step(info)); break; case SND_CTL_ELEM_TYPE_INTEGER64: printf(",min=%Li,max=%Li,step=%Li\n", snd_ctl_elem_info_get_min64(info), snd_ctl_elem_info_get_max64(info), snd_ctl_elem_info_get_step64(info)); break; case SND_CTL_ELEM_TYPE_ENUMERATED: { unsigned int items = snd_ctl_elem_info_get_items(info); printf(",items=%u\n", items); for (item = 0; item < items; item++) { snd_ctl_elem_info_set_item(info, item); if ((err = snd_hctl_elem_info(elem, info)) < 0) { error("Control %s element info error: %s\n", card, snd_strerror(err)); return err; } printf("%s; Item #%u '%s'\n", space, item, snd_ctl_elem_info_get_item_name(info)); } break; } default: printf("\n"); break; } if (level & LEVEL_BASIC) { if ((err = snd_hctl_elem_read(elem, control)) < 0) { error("Control %s element read error: %s\n", card, snd_strerror(err)); return err; } printf("%s: values=", space); for (idx = 0; idx < count; idx++) { if (idx > 0) printf(","); switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: printf("%s", snd_ctl_elem_value_get_boolean(control, idx) ? "on" : "off"); break; case SND_CTL_ELEM_TYPE_INTEGER: printf("%li", snd_ctl_elem_value_get_integer(control, idx)); break; case SND_CTL_ELEM_TYPE_INTEGER64: printf("%Li", snd_ctl_elem_value_get_integer64(control, idx)); break; case SND_CTL_ELEM_TYPE_ENUMERATED: printf("%u", snd_ctl_elem_value_get_enumerated(control, idx)); break; case SND_CTL_ELEM_TYPE_BYTES: printf("0x%02x", snd_ctl_elem_value_get_byte(control, idx)); break; default: printf("?"); break; } } printf("\n"); } return 0; }
static int show_control(const char *space, snd_hctl_elem_t *elem, int level) { int err; unsigned int item, idx, count, *tlv; snd_ctl_elem_type_t type; snd_ctl_elem_id_t *id; snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *control; snd_aes_iec958_t iec958; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_alloca(&info); snd_ctl_elem_value_alloca(&control); if ((err = snd_hctl_elem_info(elem, info)) < 0) { error("Control %s snd_hctl_elem_info error: %s\n", card, snd_strerror(err)); return err; } if (level & LEVEL_ID) { snd_hctl_elem_get_id(elem, id); show_control_id(id); printf("\n"); } count = snd_ctl_elem_info_get_count(info); type = snd_ctl_elem_info_get_type(info); printf("%s; type=%s,access=%s,values=%i", space, control_type(info), control_access(info), count); switch (type) { case SND_CTL_ELEM_TYPE_INTEGER: printf(",min=%li,max=%li,step=%li\n", snd_ctl_elem_info_get_min(info), snd_ctl_elem_info_get_max(info), snd_ctl_elem_info_get_step(info)); break; case SND_CTL_ELEM_TYPE_INTEGER64: printf(",min=%Li,max=%Li,step=%Li\n", snd_ctl_elem_info_get_min64(info), snd_ctl_elem_info_get_max64(info), snd_ctl_elem_info_get_step64(info)); break; case SND_CTL_ELEM_TYPE_ENUMERATED: { unsigned int items = snd_ctl_elem_info_get_items(info); printf(",items=%u\n", items); for (item = 0; item < items; item++) { snd_ctl_elem_info_set_item(info, item); if ((err = snd_hctl_elem_info(elem, info)) < 0) { error("Control %s element info error: %s\n", card, snd_strerror(err)); return err; } printf("%s; Item #%u '%s'\n", space, item, snd_ctl_elem_info_get_item_name(info)); } break; } default: printf("\n"); break; } if (level & LEVEL_BASIC) { if (!snd_ctl_elem_info_is_readable(info)) goto __skip_read; if ((err = snd_hctl_elem_read(elem, control)) < 0) { error("Control %s element read error: %s\n", card, snd_strerror(err)); return err; } printf("%s: values=", space); for (idx = 0; idx < count; idx++) { if (idx > 0) printf(","); switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: printf("%s", snd_ctl_elem_value_get_boolean(control, idx) ? "on" : "off"); break; case SND_CTL_ELEM_TYPE_INTEGER: printf("%li", snd_ctl_elem_value_get_integer(control, idx)); break; case SND_CTL_ELEM_TYPE_INTEGER64: printf("%Li", snd_ctl_elem_value_get_integer64(control, idx)); break; case SND_CTL_ELEM_TYPE_ENUMERATED: printf("%u", snd_ctl_elem_value_get_enumerated(control, idx)); break; case SND_CTL_ELEM_TYPE_BYTES: printf("0x%02x", snd_ctl_elem_value_get_byte(control, idx)); break; case SND_CTL_ELEM_TYPE_IEC958: snd_ctl_elem_value_get_iec958(control, &iec958); printf("[AES0=0x%02x AES1=0x%02x AES2=0x%02x AES3=0x%02x]", iec958.status[0], iec958.status[1], iec958.status[2], iec958.status[3]); break; default: printf("?"); break; } } printf("\n"); __skip_read: if (!snd_ctl_elem_info_is_tlv_readable(info)) goto __skip_tlv; tlv = malloc(4096); if ((err = snd_hctl_elem_tlv_read(elem, tlv, 4096)) < 0) { error("Control %s element TLV read error: %s\n", card, snd_strerror(err)); free(tlv); return err; } decode_tlv(strlen(space), tlv, 4096); free(tlv); } __skip_tlv: return 0; }
bool LegacyAmixerControl::accessHW(bool receive, string &error) { CAutoLog autoLog(getConfigurableElement(), "ALSA", isDebugEnabled()); #ifdef SIMULATION if (receive) { memset(getBlackboardLocation(), 0, getSize()); } log_info("%s ALSA Element Instance: %s\t\t(Control Element: %s)", receive ? "Reading" : "Writing", getConfigurableElement()->getPath().c_str(), getControlName().c_str()); return true; #endif int ret; // Mixer handle snd_ctl_t *sndCtrl; uint32_t value; uint32_t index; uint32_t elementCount; snd_ctl_elem_id_t *id; snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *control; logControlInfo(receive); // Check parameter type is ok (deferred error, no exceptions available :-() if (!isTypeSupported()) { error = "Parameter type not supported."; return false; } int cardNumber = getCardNumber(); if (cardNumber < 0) { error = "Card " + getCardName() + " not found. Error: " + strerror(cardNumber); return false; } #ifdef ANDROID if ((ret = snd_ctl_hw_open(&sndCtrl, NULL, cardNumber, 0)) < 0) { error = snd_strerror(ret); return false; } #else // Create device name ostringstream deviceName; deviceName << "hw:" << cardNumber; // Open sound control if ((ret = snd_ctl_open(&sndCtrl, deviceName.str().c_str(), 0)) < 0) { error = snd_strerror(ret); return false; } #endif // Allocate in stack snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_alloca(&info); snd_ctl_elem_value_alloca(&control); // Set interface snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); string controlName = getControlName(); // Set name or id if (isdigit(controlName[0])) { snd_ctl_elem_id_set_numid(id, asInteger(controlName)); } else { snd_ctl_elem_id_set_name(id, controlName.c_str()); } // Init info id snd_ctl_elem_info_set_id(info, id); // Get info if ((ret = snd_ctl_elem_info(sndCtrl, info)) < 0) { error = "ALSA: Unable to get element info " + controlName + ": " + snd_strerror(ret); // Close sound control snd_ctl_close(sndCtrl); return false; } // Get type snd_ctl_elem_type_t eType = snd_ctl_elem_info_get_type(info); // Get element count elementCount = snd_ctl_elem_info_get_count(info); uint32_t scalarSize = getScalarSize(); // If size defined in the PFW different from alsa mixer control size, return an error if (elementCount * scalarSize != getSize()) { error = "ALSA: Control element count (" + asString(elementCount) + ") and configurable scalar element count (" + asString(getSize() / scalarSize) + ") mismatch"; // Close sound control snd_ctl_close(sndCtrl); return false; } // Set value id snd_ctl_elem_value_set_id(control, id); if (receive) { // Read element if ((ret = snd_ctl_elem_read(sndCtrl, control)) < 0) { error = "ALSA: Unable to read element " + controlName + ": " + snd_strerror(ret); // Close sound control snd_ctl_close(sndCtrl); return false; } // Go through all indexes for (index = 0; index < elementCount; index++) { switch (eType) { case SND_CTL_ELEM_TYPE_BOOLEAN: value = snd_ctl_elem_value_get_boolean(control, index); break; case SND_CTL_ELEM_TYPE_INTEGER: value = snd_ctl_elem_value_get_integer(control, index); break; case SND_CTL_ELEM_TYPE_INTEGER64: value = snd_ctl_elem_value_get_integer64(control, index); break; case SND_CTL_ELEM_TYPE_ENUMERATED: value = snd_ctl_elem_value_get_enumerated(control, index); break; case SND_CTL_ELEM_TYPE_BYTES: value = snd_ctl_elem_value_get_byte(control, index); break; default: error = "ALSA: Unknown control element type while reading alsa element " + controlName; return false; } if (isDebugEnabled()) { log_info("Reading alsa element %s, index %u with value %u", controlName.c_str(), index, value); } // Write data to blackboard (beware this code is OK on Little Endian machines only) toBlackboard(value); } } else { // Go through all indexes for (index = 0; index < elementCount; index++) { // Read data from blackboard (beware this code is OK on Little Endian machines only) value = fromBlackboard(); if (isDebugEnabled()) { log_info("Writing alsa element %s, index %u with value %u", controlName.c_str(), index, value); } switch (eType) { case SND_CTL_ELEM_TYPE_BOOLEAN: snd_ctl_elem_value_set_boolean(control, index, value); break; case SND_CTL_ELEM_TYPE_INTEGER: snd_ctl_elem_value_set_integer(control, index, value); break; case SND_CTL_ELEM_TYPE_INTEGER64: snd_ctl_elem_value_set_integer64(control, index, value); break; case SND_CTL_ELEM_TYPE_ENUMERATED: snd_ctl_elem_value_set_enumerated(control, index, value); break; case SND_CTL_ELEM_TYPE_BYTES: snd_ctl_elem_value_set_byte(control, index, value); break; default: error = "ALSA: Unknown control element type while writing alsa element " + controlName; return false; } } // Write element if ((ret = snd_ctl_elem_write(sndCtrl, control)) < 0) { error = "ALSA: Unable to write element " + controlName + ": " + snd_strerror(ret); // Close sound control snd_ctl_close(sndCtrl); return false; } } // Close sound control snd_ctl_close(sndCtrl); return true; }
static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *top) { snd_ctl_elem_value_t *ctl; snd_ctl_elem_info_t *info; snd_config_t *control, *comment, *item, *value; const char *s; char buf[256]; unsigned int idx; int err; unsigned int device, subdevice, index; const char *name; snd_ctl_elem_type_t type; unsigned int count; snd_ctl_elem_value_alloca(&ctl); snd_ctl_elem_info_alloca(&info); snd_ctl_elem_info_set_id(info, id); err = snd_ctl_elem_info(handle, info); if (err < 0) { error("Cannot read control info '%s': %s", id_str(id), snd_strerror(err)); return err; } if (snd_ctl_elem_info_is_inactive(info) || !snd_ctl_elem_info_is_readable(info)) return 0; snd_ctl_elem_value_set_id(ctl, id); err = snd_ctl_elem_read(handle, ctl); if (err < 0) { error("Cannot read control '%s': %s", id_str(id), snd_strerror(err)); return err; } err = snd_config_compound_add(top, num_str(snd_ctl_elem_info_get_numid(info)), 0, &control); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); return err; } err = snd_config_compound_add(control, "comment", 1, &comment); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); return err; } buf[0] = '\0'; buf[1] = '\0'; if (snd_ctl_elem_info_is_readable(info)) strcat(buf, " read"); if (snd_ctl_elem_info_is_writable(info)) strcat(buf, " write"); if (snd_ctl_elem_info_is_inactive(info)) strcat(buf, " inactive"); if (snd_ctl_elem_info_is_volatile(info)) strcat(buf, " volatile"); if (snd_ctl_elem_info_is_locked(info)) strcat(buf, " locked"); if (snd_ctl_elem_info_is_user(info)) strcat(buf, " user"); err = snd_config_string_add(comment, "access", buf + 1); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } type = snd_ctl_elem_info_get_type(info); device = snd_ctl_elem_info_get_device(info); subdevice = snd_ctl_elem_info_get_subdevice(info); index = snd_ctl_elem_info_get_index(info); name = snd_ctl_elem_info_get_name(info); count = snd_ctl_elem_info_get_count(info); s = snd_ctl_elem_type_name(type); err = snd_config_string_add(comment, "type", s); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } err = snd_config_integer_add(comment, "count", count); if (err < 0) { error("snd_config_integer_add: %s", snd_strerror(err)); return err; } switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: break; case SND_CTL_ELEM_TYPE_INTEGER: { long min = snd_ctl_elem_info_get_min(info); long max = snd_ctl_elem_info_get_max(info); long step = snd_ctl_elem_info_get_step(info); if (step) sprintf(buf, "%li - %li (step %li)", min, max, step); else sprintf(buf, "%li - %li", min, max); err = snd_config_string_add(comment, "range", buf); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } if (snd_ctl_elem_info_is_tlv_readable(info)) { err = add_tlv_comments(handle, id, info, comment); if (err < 0) return err; } break; } case SND_CTL_ELEM_TYPE_INTEGER64: { long long min = snd_ctl_elem_info_get_min64(info); long long max = snd_ctl_elem_info_get_max64(info); long long step = snd_ctl_elem_info_get_step64(info); if (step) sprintf(buf, "%Li - %Li (step %Li)", min, max, step); else sprintf(buf, "%Li - %Li", min, max); err = snd_config_string_add(comment, "range", buf); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } break; } case SND_CTL_ELEM_TYPE_ENUMERATED: { unsigned int items; err = snd_config_compound_add(comment, "item", 1, &item); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); return err; } items = snd_ctl_elem_info_get_items(info); for (idx = 0; idx < items; idx++) { snd_ctl_elem_info_set_item(info, idx); err = snd_ctl_elem_info(handle, info); if (err < 0) { error("snd_ctl_card_info: %s", snd_strerror(err)); return err; } err = snd_config_string_add(item, num_str(idx), snd_ctl_elem_info_get_item_name(info)); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } } break; } default: break; } s = snd_ctl_elem_iface_name(snd_ctl_elem_info_get_interface(info)); err = snd_config_string_add(control, "iface", s); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } if (device != 0) { err = snd_config_integer_add(control, "device", device); if (err < 0) { error("snd_config_integer_add: %s", snd_strerror(err)); return err; } } if (subdevice != 0) { err = snd_config_integer_add(control, "subdevice", subdevice); if (err < 0) { error("snd_config_integer_add: %s", snd_strerror(err)); return err; } } err = snd_config_string_add(control, "name", name); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } if (index != 0) { err = snd_config_integer_add(control, "index", index); if (err < 0) { error("snd_config_integer_add: %s", snd_strerror(err)); return err; } } switch (type) { case SND_CTL_ELEM_TYPE_BYTES: case SND_CTL_ELEM_TYPE_IEC958: { size_t size = type == SND_CTL_ELEM_TYPE_BYTES ? count : sizeof(snd_aes_iec958_t); char buf[size * 2 + 1]; char *p = buf; char *hex = "0123456789abcdef"; const unsigned char *bytes = (const unsigned char *)snd_ctl_elem_value_get_bytes(ctl); for (idx = 0; idx < size; idx++) { int v = bytes[idx]; *p++ = hex[v >> 4]; *p++ = hex[v & 0x0f]; } *p = '\0'; err = snd_config_string_add(control, "value", buf); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } return 0; } default: break; } if (count == 1) { switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: err = snd_config_string_add(control, "value", snd_ctl_elem_value_get_boolean(ctl, 0) ? "true" : "false"); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } return 0; case SND_CTL_ELEM_TYPE_INTEGER: err = snd_config_integer_add(control, "value", snd_ctl_elem_value_get_integer(ctl, 0)); if (err < 0) { error("snd_config_integer_add: %s", snd_strerror(err)); return err; } return 0; case SND_CTL_ELEM_TYPE_INTEGER64: err = snd_config_integer64_add(control, "value", snd_ctl_elem_value_get_integer64(ctl, 0)); if (err < 0) { error("snd_config_integer64_add: %s", snd_strerror(err)); return err; } return 0; case SND_CTL_ELEM_TYPE_ENUMERATED: { unsigned int v = snd_ctl_elem_value_get_enumerated(ctl, 0); snd_config_t *c; err = snd_config_search(item, num_str(v), &c); if (err == 0) { err = snd_config_get_string(c, &s); assert(err == 0); err = snd_config_string_add(control, "value", s); } else { err = snd_config_integer_add(control, "value", v); } if (err < 0) error("snd_config add: %s", snd_strerror(err)); return 0; } default: error("Unknown control type: %d\n", type); return -EINVAL; } } err = snd_config_compound_add(control, "value", 1, &value); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); return err; } switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: for (idx = 0; idx < count; idx++) { err = snd_config_string_add(value, num_str(idx), snd_ctl_elem_value_get_boolean(ctl, idx) ? "true" : "false"); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } } break; case SND_CTL_ELEM_TYPE_INTEGER: for (idx = 0; idx < count; idx++) { err = snd_config_integer_add(value, num_str(idx), snd_ctl_elem_value_get_integer(ctl, idx)); if (err < 0) { error("snd_config_integer_add: %s", snd_strerror(err)); return err; } } break; case SND_CTL_ELEM_TYPE_INTEGER64: for (idx = 0; idx < count; idx++) { err = snd_config_integer64_add(value, num_str(idx), snd_ctl_elem_value_get_integer64(ctl, idx)); if (err < 0) { error("snd_config_integer64_add: %s", snd_strerror(err)); return err; } } break; case SND_CTL_ELEM_TYPE_ENUMERATED: for (idx = 0; idx < count; idx++) { unsigned int v = snd_ctl_elem_value_get_enumerated(ctl, idx); snd_config_t *c; err = snd_config_search(item, num_str(v), &c); if (err == 0) { err = snd_config_get_string(c, &s); assert(err == 0); err = snd_config_string_add(value, num_str(idx), s); } else { err = snd_config_integer_add(value, num_str(idx), v); } if (err < 0) { error("snd_config add: %s", snd_strerror(err)); return err; } } break; default: error("Unknown control type: %d\n", type); return -EINVAL; } return 0; }
/** * alsa dumy codec controls interface */ int dummy_alsa_control_raw(char * id_string , long vol, int rw, long * value){ int err; snd_hctl_t *hctl; snd_ctl_elem_id_t *id; snd_hctl_elem_t *elem; snd_ctl_elem_value_t *control; snd_ctl_elem_info_t *info; snd_ctl_elem_type_t type; unsigned int idx = 0, count; long tmp, min, max; char dev[10] = {0}; int card = alsa_get_aml_card(); int port = alsa_get_spdif_port(); adec_print("card = %d, port = %d\n", card, port); sprintf(dev, "hw:%d,%d", (card >= 0) ? card : 0, (port >= 0) ? port : 0); if ((err = snd_hctl_open(&hctl, dev, 0)) < 0) { printf("Control %s open error: %s\n", dev, snd_strerror(err)); return err; } if (err = snd_hctl_load(hctl)< 0) { printf("Control %s open error: %s\n", dev, snd_strerror(err)); return err; } snd_ctl_elem_id_alloca(&id); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_id_set_name(id, id_string); elem = snd_hctl_find_elem(hctl, id); snd_ctl_elem_value_alloca(&control); snd_ctl_elem_value_set_id(control, id); snd_ctl_elem_info_alloca(&info); if ((err = snd_hctl_elem_info(elem, info)) < 0) { printf("Control %s snd_hctl_elem_info error: %s\n", dev, snd_strerror(err)); return err; } count = snd_ctl_elem_info_get_count(info); type = snd_ctl_elem_info_get_type(info); for (idx = 0; idx < count; idx++) { switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: if(rw){ tmp = 0; if (vol >= 1) { tmp = 1; } snd_ctl_elem_value_set_boolean(control, idx, tmp); err = snd_hctl_elem_write(elem, control); }else *value = snd_ctl_elem_value_get_boolean(control, idx); break; case SND_CTL_ELEM_TYPE_INTEGER: if(rw){ min = snd_ctl_elem_info_get_min(info); max = snd_ctl_elem_info_get_max(info); if ((vol >= min) && (vol <= max)) tmp = vol; else if (vol < min) tmp = min; else if (vol > max) tmp = max; snd_ctl_elem_value_set_integer(control, idx, tmp); err = snd_hctl_elem_write(elem, control); }else *value = snd_ctl_elem_value_get_integer(control, idx); break; default: printf("?"); break; } if (err < 0){ printf ("control%s access error=%s,close control device\n", dev, snd_strerror(err)); snd_hctl_close(hctl); return err; } } return 0; }
/************************************************************************** * ALSA_CheckSetVolume [internal] * * Helper function for Alsa volume queries. This tries to simplify * the process of managing the volume. All parameters are optional * (pass NULL to ignore or not use). * Return values are MMSYSERR_NOERROR on success, or !0 on failure; * error codes are normalized into the possible documented return * values from waveOutGetVolume. */ int ALSA_CheckSetVolume(snd_hctl_t *hctl, int *out_left, int *out_right, int *out_min, int *out_max, int *out_step, int *new_left, int *new_right) { int rc = MMSYSERR_NOERROR; int value_count = 0; snd_hctl_elem_t * elem = NULL; snd_ctl_elem_info_t * eleminfop = NULL; snd_ctl_elem_value_t * elemvaluep = NULL; snd_ctl_elem_id_t * elemidp = NULL; const char *names[] = {"PCM Playback Volume", "Line Playback Volume", NULL}; const char **name; #define EXIT_ON_ERROR(f,txt,exitcode) do \ { \ int err; \ if ( (err = (f) ) < 0) \ { \ ERR(txt " failed: %s\n", snd_strerror(err)); \ rc = exitcode; \ goto out; \ } \ } while(0) if (! hctl) return MMSYSERR_NOTSUPPORTED; /* Allocate areas to return information about the volume */ EXIT_ON_ERROR(snd_ctl_elem_id_malloc(&elemidp), "snd_ctl_elem_id_malloc", MMSYSERR_NOMEM); EXIT_ON_ERROR(snd_ctl_elem_value_malloc (&elemvaluep), "snd_ctl_elem_value_malloc", MMSYSERR_NOMEM); EXIT_ON_ERROR(snd_ctl_elem_info_malloc (&eleminfop), "snd_ctl_elem_info_malloc", MMSYSERR_NOMEM); snd_ctl_elem_id_clear(elemidp); snd_ctl_elem_value_clear(elemvaluep); snd_ctl_elem_info_clear(eleminfop); /* Setup and find an element id that exactly matches the characteristic we want ** FIXME: It is probably short sighted to hard code and fixate on PCM Playback Volume */ for( name = names; *name; name++ ) { snd_ctl_elem_id_set_name(elemidp, *name); snd_ctl_elem_id_set_interface(elemidp, SND_CTL_ELEM_IFACE_MIXER); elem = snd_hctl_find_elem(hctl, elemidp); if (elem) { /* Read and return volume information */ EXIT_ON_ERROR(snd_hctl_elem_info(elem, eleminfop), "snd_hctl_elem_info", MMSYSERR_NOTSUPPORTED); value_count = snd_ctl_elem_info_get_count(eleminfop); if (out_min || out_max || out_step) { if (!snd_ctl_elem_info_is_readable(eleminfop)) { ERR("snd_ctl_elem_info_is_readable returned false; cannot return info\n"); rc = MMSYSERR_NOTSUPPORTED; goto out; } if (out_min) *out_min = snd_ctl_elem_info_get_min(eleminfop); if (out_max) *out_max = snd_ctl_elem_info_get_max(eleminfop); if (out_step) *out_step = snd_ctl_elem_info_get_step(eleminfop); } if (out_left || out_right) { EXIT_ON_ERROR(snd_hctl_elem_read(elem, elemvaluep), "snd_hctl_elem_read", MMSYSERR_NOTSUPPORTED); if (out_left) *out_left = snd_ctl_elem_value_get_integer(elemvaluep, 0); if (out_right) { if (value_count == 1) *out_right = snd_ctl_elem_value_get_integer(elemvaluep, 0); else if (value_count == 2) *out_right = snd_ctl_elem_value_get_integer(elemvaluep, 1); else { ERR("Unexpected value count %d from snd_ctl_elem_info_get_count while getting volume info\n", value_count); rc = -1; goto out; } } } /* Set the volume */ if (new_left || new_right) { EXIT_ON_ERROR(snd_hctl_elem_read(elem, elemvaluep), "snd_hctl_elem_read", MMSYSERR_NOTSUPPORTED); if (new_left) snd_ctl_elem_value_set_integer(elemvaluep, 0, *new_left); if (new_right) { if (value_count == 1) snd_ctl_elem_value_set_integer(elemvaluep, 0, *new_right); else if (value_count == 2) snd_ctl_elem_value_set_integer(elemvaluep, 1, *new_right); else { ERR("Unexpected value count %d from snd_ctl_elem_info_get_count while setting volume info\n", value_count); rc = -1; goto out; } } EXIT_ON_ERROR(snd_hctl_elem_write(elem, elemvaluep), "snd_hctl_elem_write", MMSYSERR_NOTSUPPORTED); } break; } } if( !*name ) { ERR("Could not find '{PCM,Line} Playback Volume' element\n"); rc = MMSYSERR_NOTSUPPORTED; } #undef EXIT_ON_ERROR out: if (elemvaluep) snd_ctl_elem_value_free(elemvaluep); if (eleminfop) snd_ctl_elem_info_free(eleminfop); if (elemidp) snd_ctl_elem_id_free(elemidp); return rc; }