static void hammerfall_check_sync (hammerfall_t *h, snd_ctl_elem_value_t *ctl) { const char *name; int val; snd_ctl_elem_id_t *ctl_id; jack_info ("check sync"); snd_ctl_elem_id_alloca (&ctl_id); snd_ctl_elem_value_get_id (ctl, ctl_id); name = snd_ctl_elem_id_get_name (ctl_id); if (strcmp (name, "ADAT1 Sync Check") == 0) { val = snd_ctl_elem_value_get_enumerated (ctl, 0); hammerfall_check_sync_state (h, val, 0); } else if (strcmp (name, "ADAT2 Sync Check") == 0) { val = snd_ctl_elem_value_get_enumerated (ctl, 0); hammerfall_check_sync_state (h, val, 1); } else if (strcmp (name, "ADAT3 Sync Check") == 0) { val = snd_ctl_elem_value_get_enumerated (ctl, 0); hammerfall_check_sync_state (h, val, 2); } else { jack_error ("Hammerfall: unknown control \"%s\"", name); } }
static int elem_read_enum(selem_none_t *s) { snd_ctl_elem_value_t *ctl; unsigned int idx; int err; int type; selem_ctl_t *c; type = CTL_GLOBAL_ENUM; if ( (s->selem.caps & (SM_CAP_CENUM | SM_CAP_PENUM)) == (SM_CAP_CENUM | SM_CAP_PENUM) ) type = CTL_GLOBAL_ENUM; else if (s->selem.caps & SM_CAP_PENUM) type = CTL_PLAYBACK_ENUM; else if (s->selem.caps & SM_CAP_CENUM) type = CTL_CAPTURE_ENUM; 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[0].channels; idx++) { unsigned int idx1 = idx; if (idx >= c->values) idx1 = 0; s->str[0].vol[idx] = snd_ctl_elem_value_get_enumerated(ctl, idx1); } return 0; }
static int get_toggle_index(int stream) { int err, out; snd_ctl_elem_value_t *val; stream--; if (stream < 0 || stream > 9) { g_print("get_toggle_index (1)\n"); return 0; } snd_ctl_elem_value_alloca(&val); snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); if (stream >= MAX_OUTPUT_CHANNELS) { snd_ctl_elem_value_set_name(val, SPDIF_PLAYBACK_ROUTE_NAME); snd_ctl_elem_value_set_index(val, stream - MAX_OUTPUT_CHANNELS); } else { snd_ctl_elem_value_set_name(val, ANALOG_PLAYBACK_ROUTE_NAME); snd_ctl_elem_value_set_index(val, stream); } if ((err = snd_ctl_elem_read(ctl, val)) < 0) return 0; out = snd_ctl_elem_value_get_enumerated(val, 0); if (out >= MAX_INPUT_CHANNELS + MAX_SPDIF_CHANNELS + 1) { if (stream >= MAX_PCM_OUTPUT_CHANNELS || stream < MAX_SPDIF_CHANNELS) return 1; /* digital mixer */ } else if (out >= MAX_INPUT_CHANNELS + 1) return out - (MAX_INPUT_CHANNELS + 1) + 2; /* spdif left (=2) / right (=3) */ else if (out >= 1) return out + spdif_channels + 1; /* analog (4-) */ return 0; /* pcm */ }
static void change_enum_elem_members(struct elem_set_trial *trial, snd_ctl_elem_value_t *elem_data) { unsigned int val; unsigned int i; for (i = 0; i < trial->member_count; ++i) { val = snd_ctl_elem_value_get_enumerated(elem_data, i); snd_ctl_elem_value_set_enumerated(elem_data, i, ++val); } }
void adc_sense_update(int idx) { snd_ctl_elem_value_t *val; int err; int state; 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, ADC_SENSE_NAME); snd_ctl_elem_value_set_index(val, idx); if ((err = snd_ctl_elem_read(ctl, val)) < 0) { g_print("Unable to read adc sense: %s\n", snd_strerror(err)); return; } state = snd_ctl_elem_value_get_enumerated(val, 0); toggle_set(av_adc_sense_radio[idx][state], TRUE); }
int configure_T2_DAC2_AnalogR_Playback_Volume(snd_ctl_t *ctl,char on_off_status) { snd_ctl_elem_value_t *value; snd_ctl_elem_value_alloca(&value); snd_ctl_elem_value_set_interface(value, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_value_set_name(value, control_elements_of_interest[6]); if (on_off_status) { g_t2_default_dac2_analogr = snd_ctl_elem_value_get_enumerated(value,0); snd_ctl_elem_value_set_enumerated(value,0, on_off_status); } else { snd_ctl_elem_value_set_enumerated(value,0, g_t2_default_dac2_analogr); } return(snd_ctl_elem_write(ctl, value)); }
static int get_enum_item_ops(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int *itemp) { selem_none_t *s = snd_mixer_elem_get_private(elem); snd_ctl_elem_value_t *ctl; snd_hctl_elem_t *helem; int err; if ((unsigned int) channel >= s->str[0].channels) return -EINVAL; helem = s->ctls[CTL_GLOBAL_ENUM].elem; if (!helem) helem = s->ctls[CTL_PLAYBACK_ENUM].elem; if (!helem) helem = s->ctls[CTL_CAPTURE_ENUM].elem; assert(helem); snd_ctl_elem_value_alloca(&ctl); err = snd_hctl_elem_read(helem, ctl); if (! err) *itemp = snd_ctl_elem_value_get_enumerated(ctl, channel); return err; }
/* Get the current value of the routing control */ static unsigned int utils_alsa_get_route() { int err; snd_ctl_elem_value_t *control; if(utils_alsa_init() || !utils_alsa_route_elem || !utils_alsa_route_elem_id) return -1; debug("utils_alsa_get_route: start ...\n"); snd_ctl_elem_value_alloca(&control); snd_ctl_elem_value_set_id(control, utils_alsa_route_elem_id); if((err=snd_hctl_elem_read(utils_alsa_route_elem, control))){ error("utils_alsa_get_route: read failed: %s\n", snd_strerror(err)); return -1; } unsigned int v=snd_ctl_elem_value_get_enumerated(control, 0); debug("utils_alsa_get_route: read value=%ud\n", v); return v; }
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 selem_read(snd_mixer_elem_t *elem) { selem_none_t *s; unsigned int idx; int err = 0; long pvol[32], cvol[32]; unsigned int psw, csw; assert(snd_mixer_elem_get_type(elem) == SND_MIXER_ELEM_SIMPLE); s = snd_mixer_elem_get_private(elem); memcpy(pvol, s->str[SM_PLAY].vol, sizeof(pvol)); memset(&s->str[SM_PLAY].vol, 0, sizeof(s->str[SM_PLAY].vol)); psw = s->str[SM_PLAY].sw; s->str[SM_PLAY].sw = ~0U; memcpy(cvol, s->str[SM_CAPT].vol, sizeof(cvol)); memset(&s->str[SM_CAPT].vol, 0, sizeof(s->str[SM_CAPT].vol)); csw = s->str[SM_CAPT].sw; s->str[SM_CAPT].sw = ~0U; if (s->ctls[CTL_GLOBAL_ENUM].elem) { err = elem_read_enum(s); if (err < 0) return err; goto __skip_cswitch; } if (s->ctls[CTL_CAPTURE_ENUM].elem) { err = elem_read_enum(s); if (err < 0) return err; goto __skip_cswitch; } if (s->ctls[CTL_PLAYBACK_ENUM].elem) { err = elem_read_enum(s); if (err < 0) return err; goto __skip_cswitch; } if (s->ctls[CTL_PLAYBACK_VOLUME].elem) err = elem_read_volume(s, SM_PLAY, CTL_PLAYBACK_VOLUME); else if (s->ctls[CTL_GLOBAL_VOLUME].elem) err = elem_read_volume(s, SM_PLAY, CTL_GLOBAL_VOLUME); else if (s->ctls[CTL_SINGLE].elem && s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_INTEGER) err = elem_read_volume(s, SM_PLAY, CTL_SINGLE); if (err < 0) return err; if ((s->selem.caps & (SM_CAP_GSWITCH|SM_CAP_PSWITCH)) == 0) { s->str[SM_PLAY].sw = 0; goto __skip_pswitch; } if (s->ctls[CTL_PLAYBACK_SWITCH].elem) { err = elem_read_switch(s, SM_PLAY, CTL_PLAYBACK_SWITCH); if (err < 0) return err; } if (s->ctls[CTL_GLOBAL_SWITCH].elem) { err = elem_read_switch(s, SM_PLAY, CTL_GLOBAL_SWITCH); if (err < 0) return err; } if (s->ctls[CTL_SINGLE].elem && s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_BOOLEAN) { err = elem_read_switch(s, SM_PLAY, CTL_SINGLE); if (err < 0) return err; } if (s->ctls[CTL_PLAYBACK_ROUTE].elem) { err = elem_read_route(s, SM_PLAY, CTL_PLAYBACK_ROUTE); if (err < 0) return err; } if (s->ctls[CTL_GLOBAL_ROUTE].elem) { err = elem_read_route(s, SM_PLAY, CTL_GLOBAL_ROUTE); if (err < 0) return err; } __skip_pswitch: if (s->ctls[CTL_CAPTURE_VOLUME].elem) err = elem_read_volume(s, SM_CAPT, CTL_CAPTURE_VOLUME); else if (s->ctls[CTL_GLOBAL_VOLUME].elem) err = elem_read_volume(s, SM_CAPT, CTL_GLOBAL_VOLUME); else if (s->ctls[CTL_SINGLE].elem && s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_INTEGER) err = elem_read_volume(s, SM_CAPT, CTL_SINGLE); if (err < 0) return err; if ((s->selem.caps & (SM_CAP_GSWITCH|SM_CAP_CSWITCH)) == 0) { s->str[SM_CAPT].sw = 0; goto __skip_cswitch; } if (s->ctls[CTL_CAPTURE_SWITCH].elem) { err = elem_read_switch(s, SM_CAPT, CTL_CAPTURE_SWITCH); if (err < 0) return err; } if (s->ctls[CTL_GLOBAL_SWITCH].elem) { err = elem_read_switch(s, SM_CAPT, CTL_GLOBAL_SWITCH); if (err < 0) return err; } if (s->ctls[CTL_SINGLE].elem && s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_BOOLEAN) { err = elem_read_switch(s, SM_CAPT, CTL_SINGLE); if (err < 0) return err; } if (s->ctls[CTL_CAPTURE_ROUTE].elem) { err = elem_read_route(s, SM_CAPT, CTL_CAPTURE_ROUTE); if (err < 0) return err; } if (s->ctls[CTL_GLOBAL_ROUTE].elem) { err = elem_read_route(s, SM_CAPT, CTL_GLOBAL_ROUTE); if (err < 0) return err; } if (s->ctls[CTL_CAPTURE_SOURCE].elem) { snd_ctl_elem_value_t *ctl; selem_ctl_t *c = &s->ctls[CTL_CAPTURE_SOURCE]; snd_ctl_elem_value_alloca(&ctl); err = snd_hctl_elem_read(c->elem, ctl); if (err < 0) return err; for (idx = 0; idx < s->str[SM_CAPT].channels; idx++) { unsigned int idx1 = idx; if (idx >= c->values) idx1 = 0; if (snd_ctl_elem_value_get_enumerated(ctl, idx1) != s->capture_item) s->str[SM_CAPT].sw &= ~(1 << idx); } } __skip_cswitch: if (memcmp(pvol, s->str[SM_PLAY].vol, sizeof(pvol)) || psw != s->str[SM_PLAY].sw || memcmp(cvol, s->str[SM_CAPT].vol, sizeof(cvol)) || csw != s->str[SM_CAPT].sw) return 1; return 0; }
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; }
static int check_audio_route() { int err, idx, i; snd_ctl_t *handle; const char *route_ctrl_name = "Speaker Function"; snd_ctl_elem_value_t * elem_value; snd_ctl_elem_info_t *info; snd_ctl_elem_list_t elist; snd_ctl_elem_id_t *eid; snd_ctl_elem_value_alloca(&elem_value); snd_ctl_elem_info_alloca(&info); //snd_ctl_elem_value_set_numid(elem_value, 54); if ((err = snd_ctl_open(&handle, "hw:0", 0)) < 0) { db_msg("Open control error: %s\n", snd_strerror(err)); goto check_audio_route_err; } db_msg("card=%d\n", handle->card); memset(&elist, 0, sizeof(elist)); if (snd_ctl_elem_list(handle, &elist) < 0) { db_msg("snd_ctl_elem_list 1 failed\n"); goto check_audio_route_err; } eid = calloc(elist.count, sizeof(snd_ctl_elem_id_t)); elist.space = elist.count; elist.pids = eid; if (snd_ctl_elem_list(handle, &elist) < 0) { db_msg("snd_ctl_elem_list 2 failed\n"); goto check_audio_route_err; } for (i = 0; i < elist.count; ++i) { info->id.numid = eid[i].numid; if ((err = snd_ctl_elem_info(handle, info)) < 0) { db_msg("Cannot find the given element from control\n"); goto check_audio_route_err; } //db_msg("name[%d]=%s\n", i, snd_ctl_elem_info_get_name(info)); if (!strcmp(snd_ctl_elem_info_get_name(info), route_ctrl_name)) { db_msg("route ctrl found!!!\n"); break; } } snd_ctl_elem_value_set_numid(elem_value, info->id.numid); if ((err = snd_ctl_elem_read(handle,elem_value)) < 0) { db_msg("snd_ctl_elem_read error: %s\n", snd_strerror(err)); goto check_audio_route_err; } db_msg("numid=%d\n", snd_ctl_elem_value_get_numid(elem_value)); db_msg("name=%s\n", snd_ctl_elem_value_get_name(elem_value)); //to set the new value snd_ctl_elem_value_set_enumerated(elem_value,0, 1); if ((err = snd_ctl_elem_write(handle,elem_value)) < 0) { db_msg("snd_ctl_elem_write error: %s\n", snd_strerror(err)); goto check_audio_route_err; } //read it out again to check if we did set the registers. if ((err = snd_ctl_elem_read(handle,elem_value)) < 0) { db_msg("snd_ctl_elem_read error: %s\n", snd_strerror(err)); goto check_audio_route_err; } db_msg("after: %d\n", snd_ctl_elem_value_get_enumerated(elem_value, 0)); snd_ctl_close(handle); return 0; check_audio_route_err: snd_ctl_close(handle); return -1; }