static void * hammerfall_monitor_controls (void *arg) { jack_hardware_t *hw = (jack_hardware_t *) arg; hammerfall_t *h = (hammerfall_t *) hw->private_hw; snd_ctl_elem_id_t *switch_id[3]; snd_ctl_elem_value_t *sw[3]; pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); snd_ctl_elem_id_malloc (&switch_id[0]); snd_ctl_elem_id_malloc (&switch_id[1]); snd_ctl_elem_id_malloc (&switch_id[2]); snd_ctl_elem_value_malloc (&sw[0]); snd_ctl_elem_value_malloc (&sw[1]); snd_ctl_elem_value_malloc (&sw[2]); set_control_id (switch_id[0], "ADAT1 Sync Check"); set_control_id (switch_id[1], "ADAT2 Sync Check"); set_control_id (switch_id[2], "ADAT3 Sync Check"); snd_ctl_elem_value_set_id (sw[0], switch_id[0]); snd_ctl_elem_value_set_id (sw[1], switch_id[1]); snd_ctl_elem_value_set_id (sw[2], switch_id[2]); while (1) { if (snd_ctl_elem_read (h->driver->ctl_handle, sw[0])) { jack_error ("cannot read control switch 0 ..."); } hammerfall_check_sync (h, sw[0]); if (snd_ctl_elem_read (h->driver->ctl_handle, sw[1])) { jack_error ("cannot read control switch 0 ..."); } hammerfall_check_sync (h, sw[1]); if (snd_ctl_elem_read (h->driver->ctl_handle, sw[2])) { jack_error ("cannot read control switch 0 ..."); } hammerfall_check_sync (h, sw[2]); if (nanosleep (&h->monitor_interval, 0)) { break; } } pthread_exit (0); }
static int hammerfall_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) { hammerfall_t *h = (hammerfall_t *) hw->private_hw; snd_ctl_elem_value_t *ctl; snd_ctl_elem_id_t *ctl_id; int err; int i; snd_ctl_elem_value_alloca (&ctl); snd_ctl_elem_id_alloca (&ctl_id); set_control_id (ctl_id, "Channels Thru"); snd_ctl_elem_value_set_id (ctl, ctl_id); for (i = 0; i < 26; i++) { snd_ctl_elem_value_set_integer (ctl, i, (mask & (1<<i)) ? 1 : 0); } if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) != 0) { jack_error ("ALSA/Hammerfall: cannot set input monitoring (%s)", snd_strerror (err)); return -1; } hw->input_monitor_mask = mask; return 0; }
static int hammerfall_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode) { hammerfall_t *h = (hammerfall_t *) hw->private_hw; snd_ctl_elem_value_t *ctl; snd_ctl_elem_id_t *ctl_id; int err; snd_ctl_elem_value_alloca (&ctl); snd_ctl_elem_id_alloca (&ctl_id); set_control_id (ctl_id, "Sync Mode"); snd_ctl_elem_value_set_id (ctl, ctl_id); switch (mode) { case AutoSync: snd_ctl_elem_value_set_enumerated (ctl, 0, 0); break; case ClockMaster: snd_ctl_elem_value_set_enumerated (ctl, 0, 1); break; case WordClock: snd_ctl_elem_value_set_enumerated (ctl, 0, 2); break; } if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) < 0) { jack_error ("ALSA-Hammerfall: cannot set clock mode"); } return 0; }
int V4LRadioControl::volume() const { const QString ctlName("Line DAC Playback Volume"); const QString card("hw:0"); int volume = 0; int err; static snd_ctl_t *handle = NULL; snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *control; snd_ctl_elem_info_alloca(&info); snd_ctl_elem_id_alloca(&id); snd_ctl_elem_value_alloca(&control); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); /* MIXER */ snd_ctl_elem_id_set_name(id, ctlName.toAscii()); if ((err = snd_ctl_open(&handle, card.toAscii(), 0)) < 0) { return 0; } snd_ctl_elem_info_set_id(info, id); if ((err = snd_ctl_elem_info(handle, info)) < 0) { snd_ctl_close(handle); handle = NULL; return 0; } snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */ snd_ctl_elem_value_set_id(control, id); snd_ctl_close(handle); handle = NULL; snd_hctl_t *hctl; snd_hctl_elem_t *elem; if ((err = snd_hctl_open(&hctl, card.toAscii(), 0)) < 0) { return 0; } if ((err = snd_hctl_load(hctl)) < 0) { return 0; } elem = snd_hctl_find_elem(hctl, id); if (elem) volume = vol(elem); snd_hctl_close(hctl); return (volume/118.0) * 100; }
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); }
static int execute_cset(snd_ctl_t *ctl, const char *cset) { const char *pos; int err; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *value; snd_ctl_elem_info_t *info; snd_ctl_elem_id_malloc(&id); snd_ctl_elem_value_malloc(&value); snd_ctl_elem_info_malloc(&info); err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos); if (err < 0) goto __fail; while (*pos && isspace(*pos)) pos++; if (!*pos) { uc_error("undefined value for cset >%s<", cset); err = -EINVAL; goto __fail; } snd_ctl_elem_value_set_id(value, id); snd_ctl_elem_info_set_id(info, id); err = snd_ctl_elem_read(ctl, value); if (err < 0) goto __fail; err = snd_ctl_elem_info(ctl, info); if (err < 0) goto __fail; err = snd_ctl_ascii_value_parse(ctl, value, info, pos); if (err < 0) goto __fail; err = snd_ctl_elem_write(ctl, value); if (err < 0) goto __fail; err = 0; __fail: if (id != NULL) free(id); if (value != NULL) free(value); if (info != NULL) free(info); return err; }
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 setamixer(int devnum,char *param, int v1, int v2) { int type; char str[100]; snd_hctl_t *hctl; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *control; snd_hctl_elem_t *elem; snd_ctl_elem_info_t *info; sprintf(str,"hw:%d",devnum); if (snd_hctl_open(&hctl, str, 0)) return(-1); snd_hctl_load(hctl); 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, param); elem = snd_hctl_find_elem(hctl, id); if (!elem) { snd_hctl_close(hctl); return(-1); } snd_ctl_elem_info_alloca(&info); snd_hctl_elem_info(elem,info); type = snd_ctl_elem_info_get_type(info); snd_ctl_elem_value_alloca(&control); snd_ctl_elem_value_set_id(control, id); switch(type) { case SND_CTL_ELEM_TYPE_INTEGER: snd_ctl_elem_value_set_integer(control, 0, v1); if (v2 > 0) snd_ctl_elem_value_set_integer(control, 1, v2); break; case SND_CTL_ELEM_TYPE_BOOLEAN: snd_ctl_elem_value_set_integer(control, 0, (v1 != 0)); break; } if (snd_hctl_elem_write(elem, control)) { snd_hctl_close(hctl); return(-1); } snd_hctl_close(hctl); return(0); }
/* Change the value of the routing control */ static int utils_alsa_set_route(unsigned int value) { if(utils_alsa_init() || !utils_alsa_route_elem || !utils_alsa_route_elem_id) return 1; debug("utils_alsa_set_control_enum: value=%ud\n", value); snd_ctl_elem_value_t *control; snd_ctl_elem_value_alloca(&control); snd_ctl_elem_value_set_id(control, utils_alsa_route_elem_id); snd_ctl_elem_value_set_enumerated(control, 0, value); int err=snd_hctl_elem_write(utils_alsa_route_elem, control); if(err<0){ error("utils_alsa_set_control_enum: write failed: %s\n", snd_strerror(err)); return 1; }{ debug("utils_alsa_set_control_enum: success\n"); } return 0; }
/* 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; }
/****************************************************************************** * setMixerInput *****************************************************************************/ static Int setMixerControl (const Char *name, Int value) { Int status; snd_hctl_t *hctl; snd_ctl_elem_id_t *id; snd_hctl_elem_t *elem; snd_ctl_elem_value_t *control; if ((status = snd_hctl_open(&hctl, AUDIO_MIXER, 0)) < 0) { Dmai_err2("setMixerControl %s open error: %s\n", AUDIO_MIXER, snd_strerror(status)); return Dmai_EFAIL;; } if ((status = snd_hctl_load(hctl)) < 0) { Dmai_err2("setMixerControl %s load error: %s\n", AUDIO_MIXER, snd_strerror(status)); return Dmai_EFAIL;; } 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, name); elem = snd_hctl_find_elem(hctl, id); if (!elem) { Dmai_err1("setMixerControl %s find element error\n", AUDIO_MIXER); snd_hctl_close(hctl); return Dmai_EFAIL; } snd_ctl_elem_value_alloca(&control); snd_ctl_elem_value_set_id(control, id); snd_ctl_elem_value_set_integer(control, 0, value); snd_hctl_elem_write(elem, control); snd_hctl_close(hctl); return Dmai_EOK; }
static int check_elems(struct elem_set_trial *trial) { snd_ctl_elem_value_t *data; unsigned int numid; unsigned int index; unsigned int i; int err; snd_ctl_elem_value_alloca(&data); snd_ctl_elem_value_set_id(data, trial->id); numid = snd_ctl_elem_id_get_numid(trial->id); index = snd_ctl_elem_id_get_index(trial->id); for (i = 0; i < trial->element_count; ++i) { snd_ctl_elem_value_set_index(data, index + i); /* * In Linux 4.0 or former, ioctl(SNDRV_CTL_IOCTL_ELEM_ADD) * doesn't fill all of fields for identification. */ if (numid > 0) snd_ctl_elem_value_set_numid(data, numid + i); err = snd_ctl_elem_read(trial->handle, data); if (err < 0) return err; /* Change members of an element in this element set. */ trial->change_elem_members(trial, data); err = snd_ctl_elem_write(trial->handle, data); if (err < 0) return err; } return 0; }
int hw_audio_set(const char *name, int value) { static snd_ctl_t *handle = NULL; 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); 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); if (handle == NULL && (err = snd_ctl_open(&handle, "default", 0)) < 0) { LOGE("Control default open error: %s\n", snd_strerror(err)); return 0; } int ret = snd_ctl_elem_info(handle, info); if (ret < 0) { LOGE("Cannot find the given element from control default ret=%d %s ", ret, snd_strerror(ret)); return 0; } snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(info); snd_ctl_elem_info_get_id(info, id); snd_ctl_elem_value_set_id(control, id); switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: snd_ctl_elem_value_set_boolean(control, 0, value); break; case SND_CTL_ELEM_TYPE_INTEGER: snd_ctl_elem_value_set_integer(control, 0, value); break; case SND_CTL_ELEM_TYPE_INTEGER64: snd_ctl_elem_value_set_integer64(control, 0, value); break; case SND_CTL_ELEM_TYPE_ENUMERATED: snd_ctl_elem_value_set_enumerated(control, 0, value); break; case SND_CTL_ELEM_TYPE_BYTES: snd_ctl_elem_value_set_byte(control, 0, value); break; default: break; } ret = snd_ctl_elem_write(handle, control); if(ret <0) { LOGE("Control default load error: %s\n", snd_strerror(ret)); } return 1; }
void V4LRadioControl::callAmixer(const QString& target, const QString& value) { int err; long tmp; unsigned int count; static snd_ctl_t *handle = NULL; QString card("hw:0"); snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *control; snd_ctl_elem_type_t type; snd_ctl_elem_info_alloca(&info); snd_ctl_elem_id_alloca(&id); snd_ctl_elem_value_alloca(&control); snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); /* MIXER */ // in amixer parse func // char target[64]; // e.g. PGA CAPTure Switch snd_ctl_elem_id_set_name(id, target.toAscii()); if (handle == NULL && (err = snd_ctl_open(&handle, card.toAscii(), 0)) < 0) { return; } snd_ctl_elem_info_set_id(info, id); if ((err = snd_ctl_elem_info(handle, info)) < 0) { snd_ctl_close(handle); handle = NULL; return; } snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */ type = snd_ctl_elem_info_get_type(info); count = snd_ctl_elem_info_get_count(info); snd_ctl_elem_value_set_id(control, id); tmp = 0; for (uint idx = 0; idx < count && idx < 128; idx++) { switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: #ifdef MULTIMEDIA_MAEMO_DEBUG qDebug() << "SND_CTL_ELEM_TYPE_BOOLEAN" << SND_CTL_ELEM_TYPE_BOOLEAN; #endif if ((value == "on") ||(value == "1")) { tmp = 1; } snd_ctl_elem_value_set_boolean(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_ENUMERATED: tmp = getEnumItemIndex(handle, info, value); snd_ctl_elem_value_set_enumerated(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER: #ifdef MULTIMEDIA_MAEMO_DEBUG qDebug() << "SND_CTL_ELEM_TYPE_INTEGER" << SND_CTL_ELEM_TYPE_INTEGER; #endif tmp = atoi(value.toAscii()); if (tmp < snd_ctl_elem_info_get_min(info)) tmp = snd_ctl_elem_info_get_min(info); else if (tmp > snd_ctl_elem_info_get_max(info)) tmp = snd_ctl_elem_info_get_max(info); snd_ctl_elem_value_set_integer(control, idx, tmp); break; default: break; } } if ((err = snd_ctl_elem_write(handle, control)) < 0) { snd_ctl_close(handle); handle = NULL; return; } snd_ctl_close(handle); handle = NULL; }
/** * \brief parse ASCII string as CTL element value * \param handle CTL handle * \param dst destination CTL element value * \param info CTL element info structure * \param value source ASCII string * \return zero on success, otherwise a negative error code * * Note: For toggle command, the dst must contain previous (current) * state (do the #snd_ctl_elem_read call to obtain it). */ int snd_ctl_ascii_value_parse(snd_ctl_t *handle, snd_ctl_elem_value_t *dst, snd_ctl_elem_info_t *info, const char *value) { const char *ptr = value; snd_ctl_elem_id_t myid = {0}; snd_ctl_elem_type_t type; unsigned int idx, count; long tmp; long long tmp64; snd_ctl_elem_info_get_id(info, &myid); type = snd_ctl_elem_info_get_type(info); count = snd_ctl_elem_info_get_count(info); snd_ctl_elem_value_set_id(dst, &myid); for (idx = 0; idx < count && idx < 128 && ptr && *ptr; idx++) { if (*ptr == ',') goto skip; switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: tmp = 0; if (!strncasecmp(ptr, "on", 2) || !strncasecmp(ptr, "up", 2)) { tmp = 1; ptr += 2; } else if (!strncasecmp(ptr, "yes", 3)) { tmp = 1; ptr += 3; } else if (!strncasecmp(ptr, "toggle", 6)) { tmp = snd_ctl_elem_value_get_boolean(dst, idx); tmp = tmp > 0 ? 0 : 1; ptr += 6; } else if (isdigit(*ptr)) { tmp = atoi(ptr) > 0 ? 1 : 0; while (isdigit(*ptr)) ptr++; } else { while (*ptr && *ptr != ',') ptr++; } snd_ctl_elem_value_set_boolean(dst, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER: tmp = get_integer(&ptr, snd_ctl_elem_info_get_min(info), snd_ctl_elem_info_get_max(info)); snd_ctl_elem_value_set_integer(dst, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER64: tmp64 = get_integer64(&ptr, snd_ctl_elem_info_get_min64(info), snd_ctl_elem_info_get_max64(info)); snd_ctl_elem_value_set_integer64(dst, idx, tmp64); break; case SND_CTL_ELEM_TYPE_ENUMERATED: tmp = get_ctl_enum_item_index(handle, info, &ptr); if (tmp < 0) tmp = get_integer(&ptr, 0, snd_ctl_elem_info_get_items(info) - 1); snd_ctl_elem_value_set_enumerated(dst, idx, tmp); break; case SND_CTL_ELEM_TYPE_BYTES: tmp = get_integer(&ptr, 0, 255); snd_ctl_elem_value_set_byte(dst, idx, tmp); break; default: break; } skip: if (!strchr(value, ',')) ptr = value; else if (*ptr == ',') ptr++; } return 0; }
status_t ALSAControl::set(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_id_alloca(&id); snd_ctl_elem_info_alloca(&info); 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; } if (index == -1) index = 0; // Range over all of them else count = index + 1; // Just do the one specified snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(info); snd_ctl_elem_value_t *control; snd_ctl_elem_value_alloca(&control); snd_ctl_elem_info_get_id(info, id); snd_ctl_elem_value_set_id(control, id); for (int i = index; i < count; i++) switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: snd_ctl_elem_value_set_boolean(control, i, value); break; case SND_CTL_ELEM_TYPE_INTEGER: snd_ctl_elem_value_set_integer(control, i, value); break; case SND_CTL_ELEM_TYPE_INTEGER64: snd_ctl_elem_value_set_integer64(control, i, value); break; case SND_CTL_ELEM_TYPE_ENUMERATED: snd_ctl_elem_value_set_enumerated(control, i, value); break; case SND_CTL_ELEM_TYPE_BYTES: snd_ctl_elem_value_set_byte(control, i, value); break; default: break; } ret = snd_ctl_elem_write(mHandle, control); return (ret < 0) ? BAD_VALUE : NO_ERROR; }
static int amixer_control(t_amixer *x, int argc, t_atom *argv, int roflag) { int err; snd_ctl_t *handle; snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *control; char *ptr; unsigned int idx, count; long tmp; snd_ctl_elem_type_t type; snd_ctl_elem_info_alloca(&info); snd_ctl_elem_id_alloca(&id); snd_ctl_elem_value_alloca(&control); if (argc < 1) { error("Specify a full control identifier: [[iface=<iface>,][name='name',][index=<index>,][device=<device>,][subdevice=<subdevice>]]|[numid=<numid>]\n"); return -EINVAL; } if(A_FLOAT==argv->a_type){ snd_ctl_elem_id_set_numid(id, atom_getint(argv)); if(0) { error("Wrong control identifier: %d\n", atom_getint(argv)); return -EINVAL; } } else { if (parse_control_id(atom_getsymbol(argv)->s_name, id)) { error("Wrong control identifier: %s\n", atom_getsymbol(argv)->s_name); return -EINVAL; } } if ((err = snd_ctl_open(&handle, x->card, 0)) < 0) { error("Control %s open error: %s\n", x->card, snd_strerror(err)); return err; } snd_ctl_elem_info_set_id(info, id); if ((err = snd_ctl_elem_info(handle, info)) < 0) { error("Control %s cinfo error: %s\n", x->card, snd_strerror(err)); return err; } snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */ type = snd_ctl_elem_info_get_type(info); count = snd_ctl_elem_info_get_count(info); snd_ctl_elem_value_set_id(control, id); if (!roflag) { t_float atom_float = atom_getfloat(argv+1); int atom_isfloat = (A_FLOAT==(argv+1)->a_type); post("now setting"); ptr = atom_getsymbol(argv+1)->s_name; for (idx = 0; idx < count && idx < 128 && ptr && *ptr; idx++) { switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: tmp = 0; if(atom_isfloat){ tmp=(atom_float>0)?1:0; } else if (!strncasecmp(ptr, "on", 2) || !strncasecmp(ptr, "up", 2)) { tmp = 1; ptr += 2; } else if (!strncasecmp(ptr, "yes", 3)) { tmp = 1; ptr += 3; } else if (!strncasecmp(ptr, "toggle", 6)) { tmp = snd_ctl_elem_value_get_boolean(control, idx); tmp = tmp > 0 ? 0 : 1; ptr += 6; } else if (isdigit(*ptr)) { tmp = atoi(ptr) > 0 ? 1 : 0; while (isdigit(*ptr)) ptr++; } else { while (*ptr && *ptr != ',') ptr++; } snd_ctl_elem_value_set_boolean(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER: tmp = atom_isfloat?((int)atom_float):get_integer(&ptr, snd_ctl_elem_info_get_min(info), snd_ctl_elem_info_get_max(info)); snd_ctl_elem_value_set_integer(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER64: tmp = atom_isfloat?((int)atom_float):get_integer64(&ptr, snd_ctl_elem_info_get_min64(info), snd_ctl_elem_info_get_max64(info)); snd_ctl_elem_value_set_integer64(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_ENUMERATED: tmp = atom_isfloat?((int)atom_float):get_integer(&ptr, 0, snd_ctl_elem_info_get_items(info) - 1); snd_ctl_elem_value_set_enumerated(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_BYTES: tmp = atom_isfloat?((int)atom_float):get_integer(&ptr, 0, 255); snd_ctl_elem_value_set_byte(control, idx, tmp); break; default: break; } if (!strchr(atom_getsymbol(argv+1)->s_name, ',')) ptr = atom_getsymbol(argv+1)->s_name; else if (*ptr == ',') ptr++; } if ((err = snd_ctl_elem_write(handle, control)) < 0) { error("Control %s element write error: %s\n", x->card, snd_strerror(err)); return err; } } snd_ctl_close(handle); if (1) { snd_hctl_t *hctl; snd_hctl_elem_t *elem; if ((err = snd_hctl_open(&hctl, x->card, 0)) < 0) { error("Control %s open error: %s\n", x->card, snd_strerror(err)); return err; } if ((err = snd_hctl_load(hctl)) < 0) { error("Control %s load error: %s\n", x->card, snd_strerror(err)); return err; } elem = snd_hctl_find_elem(hctl, id); if (elem) show_control(x->card, " ", elem, LEVEL_BASIC | LEVEL_ID); else printf("Could not find the specified element\n"); snd_hctl_close(hctl); } }
static int cset(int argc, char *argv[], int roflag, int keep_handle) { int err; static snd_ctl_t *handle = NULL; snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *control; char *ptr; unsigned int idx, count; long tmp; snd_ctl_elem_type_t type; snd_ctl_elem_info_alloca(&info); snd_ctl_elem_id_alloca(&id); snd_ctl_elem_value_alloca(&control); if (argc < 1) return -EINVAL; if (parse_control_id(argv[0], id)) return -EINVAL; if (handle == NULL && (err = snd_ctl_open(&handle, card, 0)) < 0) return err; snd_ctl_elem_info_set_id(info, id); if ((err = snd_ctl_elem_info(handle, info)) < 0) { if (!keep_handle) { snd_ctl_close(handle); handle = NULL; } return err; } snd_ctl_elem_info_get_id(info, id); type = snd_ctl_elem_info_get_type(info); count = snd_ctl_elem_info_get_count(info); snd_ctl_elem_value_set_id(control, id); if (!roflag) { ptr = argv[1]; for (idx = 0; idx < count && idx < 128 && ptr && *ptr; idx++) { switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: tmp = 0; if (!strncasecmp(ptr, "on", 2) || !strncasecmp(ptr, "up", 2)) { tmp = 1; ptr += 2; } else if (!strncasecmp(ptr, "yes", 3)) { tmp = 1; ptr += 3; } else if (!strncasecmp(ptr, "toggle", 6)) { tmp = snd_ctl_elem_value_get_boolean(control, idx); tmp = tmp > 0 ? 0 : 1; ptr += 6; } else if (isdigit(*ptr)) { tmp = atoi(ptr) > 0 ? 1 : 0; while (isdigit(*ptr)) ptr++; } else { while (*ptr && *ptr != ',') ptr++; } snd_ctl_elem_value_set_boolean(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER: tmp = get_integer(&ptr, snd_ctl_elem_info_get_min(info), snd_ctl_elem_info_get_max(info)); snd_ctl_elem_value_set_integer(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER64: tmp = get_integer64(&ptr, snd_ctl_elem_info_get_min64(info), snd_ctl_elem_info_get_max64(info)); snd_ctl_elem_value_set_integer64(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_ENUMERATED: tmp = get_ctl_enum_item_index(handle, info, &ptr); if (tmp < 0) tmp = get_integer(&ptr, 0, snd_ctl_elem_info_get_items(info) - 1); snd_ctl_elem_value_set_enumerated(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_BYTES: tmp = get_integer(&ptr, 0, 255); snd_ctl_elem_value_set_byte(control, idx, tmp); break; default: break; } if (!strchr(argv[1], ',')) ptr = argv[1]; else if (*ptr == ',') ptr++; } if ((err = snd_ctl_elem_write(handle, control)) < 0) { if (!keep_handle) { snd_ctl_close(handle); handle = NULL; } return err; } } if (! keep_handle) { snd_ctl_close(handle); handle = NULL; } if (!quiet) { snd_hctl_t *hctl; snd_hctl_elem_t *elem; if ((err = snd_hctl_open(&hctl, card, 0)) < 0) return err; if ((err = snd_hctl_load(hctl)) < 0) return err; elem = snd_hctl_find_elem(hctl, id); if (elem) show_control(" ", elem, LEVEL_BASIC | LEVEL_ID); snd_hctl_close(hctl); } return 0; }
void main( int argc, char *argv[] ) { struct structArgs cmdArgs; int errNum; // ************************************************************************ // 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 info container. // ************************************************************************ // Get command line parameters. // ************************************************************************ argp_parse( &argp, argc, argv, 0, 0, &cmdArgs ); printf( "Card = %i\n", cmdArgs.card ); printf( "Control = %i\n", cmdArgs.control ); printf( "Value 1 = %i\n", cmdArgs.value1 ); printf( "Value 2 = %i\n", cmdArgs.value2 ); // ************************************************************************ // Set up ALSA control. // ************************************************************************ sprintf( cmdArgs.deviceID, "hw:%i", cmdArgs.card ); printf( "Device ID = %s.\n", cmdArgs.deviceID ); if ( snd_ctl_open( &ctl, cmdArgs.deviceID, 1 ) < 0 ) { printf( "Error opening control.\n" ); return; } // Initialise a simple control element id structure. snd_ctl_elem_id_alloca( &id ); snd_ctl_elem_id_set_numid( id, cmdArgs.control ); // Initialise info element. snd_ctl_elem_info_alloca( &info ); snd_ctl_elem_info_set_numid( info, cmdArgs.control ); // Is the control valid? if ( snd_ctl_elem_info( ctl, info ) < 0 ) { printf( "Error getting control element info.\n" ); return; } // Find type of control. // either: // SND_CTL_ELEM_TYPE_INTEGER, // SND_CTL_ELEM_TYPE_INTEGER64, // SND_CTL_ELEM_TYPE_ENUMERATED, etc. // Only interested in INTEGER. type = snd_ctl_elem_info_get_type( info ); if ( type != SND_CTL_ELEM_TYPE_INTEGER ) { printf( "Control type is not integer.\n" ); printf( "Type = %s\n", type ); return; } // ************************************************************************ // Get some information for selected control. // ************************************************************************ printf( "Min value for control = %d\n", snd_ctl_elem_info_get_min( info )); printf( "Max value for control = %d\n", snd_ctl_elem_info_get_max( info )); printf( "Step value for control = %d\n", snd_ctl_elem_info_get_step( info )); // Initialise the control element value container. snd_ctl_elem_value_alloca( &control ); snd_ctl_elem_value_set_id( control, id ); // ************************************************************************ // Set values for selected control. // ************************************************************************ snd_ctl_elem_value_set_integer( control, 0, cmdArgs.value1 ); if ( snd_ctl_elem_write( ctl, control ) < 0 ) printf( "Error setting L volume" ); else printf( "Set L volume to %d.\n", cmdArgs.value1 ); snd_ctl_elem_value_set_integer( control, 1, cmdArgs.value2 ); if ( snd_ctl_elem_write( ctl, control ) < 0 ) printf( "Error setting R volume" ); else printf( "Set R volume to %d.\n", cmdArgs.value2 ); // ************************************************************************ // Clean up. // ************************************************************************ snd_ctl_close( ctl ); return; }
/* Try and find an IEC958 PCM device and mixer on card 0 and open it * This function is only used on older ALSA installs that don't have the * correct iec958 alias stuff set up, and relies on there being only * one IEC958 PCM device (relies IEC958 in the device name) and one IEC958 * mixer control for doing the settings. */ static int alsaspdifsink_find_pcm_device (AlsaSPDIFSink * sink) { int err = -1, dev, idx, count; const gchar *ctl_name = "hw:0"; const gchar *spdif_name = SND_CTL_NAME_IEC958 ("", PLAYBACK, NONE); int card = sink->card; gchar pcm_name[24]; snd_pcm_t *pcm = NULL; snd_ctl_t *ctl = NULL; snd_ctl_card_info_t *info = NULL; snd_ctl_elem_list_t *clist = NULL; snd_ctl_elem_id_t *cid = NULL; snd_pcm_info_t *pinfo = NULL; GST_WARNING ("Opening IEC958 named device failed. Trying to autodetect"); if ((err = snd_ctl_open (&ctl, ctl_name, card)) < 0) return err; snd_ctl_card_info_malloc (&info); snd_pcm_info_malloc (&pinfo); /* Find a mixer for IEC958 settings */ snd_ctl_elem_list_malloc (&clist); if ((err = snd_ctl_elem_list (ctl, clist)) < 0) goto beach; if ((err = snd_ctl_elem_list_alloc_space (clist, snd_ctl_elem_list_get_count (clist))) < 0) goto beach; if ((err = snd_ctl_elem_list (ctl, clist)) < 0) goto beach; count = snd_ctl_elem_list_get_used (clist); for (idx = 0; idx < count; idx++) { if (strstr (snd_ctl_elem_list_get_name (clist, idx), spdif_name) != NULL) break; } if (idx == count) { /* No SPDIF mixer availble */ err = 0; goto beach; } snd_ctl_elem_id_malloc (&cid); snd_ctl_elem_list_get_id (clist, idx, cid); /* Now find a PCM device for IEC 958 */ if ((err = snd_ctl_card_info (ctl, info)) < 0) goto beach; dev = -1; do { if (snd_ctl_pcm_next_device (ctl, &dev) < 0) goto beach; if (dev < 0) break; /* No more devices */ /* Filter for playback devices */ snd_pcm_info_set_device (pinfo, dev); snd_pcm_info_set_subdevice (pinfo, 0); snd_pcm_info_set_stream (pinfo, SND_PCM_STREAM_PLAYBACK); if ((err = snd_ctl_pcm_info (ctl, pinfo)) < 0) { if (err != -ENOENT) goto beach; /* Genuine error */ /* Device has no playback streams */ continue; } if (strstr (snd_pcm_info_get_name (pinfo), "IEC958") == NULL) continue; /* Not the device we are looking for */ count = snd_pcm_info_get_subdevices_count (pinfo); GST_LOG_OBJECT (sink, "Device %d has %d subdevices\n", dev, snd_pcm_info_get_subdevices_count (pinfo)); for (idx = 0; idx < count; idx++) { snd_pcm_info_set_subdevice (pinfo, idx); if ((err = snd_ctl_pcm_info (ctl, pinfo)) < 0) goto beach; g_assert (snd_pcm_info_get_stream (pinfo) == SND_PCM_STREAM_PLAYBACK); GST_LOG_OBJECT (sink, "Found playback stream on dev %d sub-d %d\n", dev, idx); /* Found a suitable PCM device, let's open it */ g_snprintf (pcm_name, 24, "hw:%d,%d", card, dev); if ((err = snd_pcm_open (&(pcm), pcm_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) goto beach; break; } } while (pcm == NULL); if (pcm != NULL) { snd_ctl_elem_value_t *cval; snd_aes_iec958_t iec958; /* Have a PCM device and a mixer, set things up */ snd_ctl_elem_value_malloc (&cval); snd_ctl_elem_value_set_id (cval, cid); snd_ctl_elem_value_get_iec958 (cval, &iec958); iec958.status[0] = IEC958_AES0_NONAUDIO; iec958.status[1] = IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER; iec958.status[2] = 0; iec958.status[3] = IEC958_AES3_CON_FS_48000; snd_ctl_elem_value_set_iec958 (cval, &iec958); snd_ctl_elem_value_free (cval); sink->pcm = pcm; pcm = NULL; err = 0; } beach: if (pcm) snd_pcm_close (pcm); if (clist) snd_ctl_elem_list_clear (clist); if (ctl) snd_ctl_close (ctl); if (clist) snd_ctl_elem_list_free (clist); if (cid) snd_ctl_elem_id_free (cid); if (info) snd_ctl_card_info_free (info); if (pinfo) snd_pcm_info_free (pinfo); return err; }
/** * 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; }
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; }
int main(int argc, char *argv[]) { char *format = FORMAT; char *device = DEVICE; char *volume_control = VOLUME_CONTROL; char *mute_control = MUTE_CONTROL; int interval = INTERVAL; bool snoop = false; int opt; while ((opt = getopt(argc, argv, "hsf:i:d:v:m:")) != -1) { switch (opt) { case 'h': printf("volume [-h|-s|-f FORMAT|-i INTERVAL|-d DEVICE|-v VOLUME_CONTROL|-m MUTE_CONTROL]\n"); exit(EXIT_SUCCESS); break; case 's': snoop = true; break; case 'f': format = optarg; break; case 'd': device = optarg; break; case 'i': interval = atoi(optarg); break; case 'v': volume_control = optarg; break; case 'm': mute_control = optarg; break; } } int exit_code; snd_hctl_t *hctl; snd_ctl_elem_id_t *volume_id; snd_ctl_elem_id_t *mute_id; snd_ctl_elem_value_t *volume_ctl; snd_ctl_elem_value_t *mute_ctl; snd_ctl_elem_info_t *volume_info; snd_hctl_elem_t *volume_elem; snd_hctl_elem_t *mute_elem; int vol_max, vol_min; if (snd_hctl_open(&hctl, device, 0) || snd_hctl_load(hctl)) { return EXIT_FAILURE; } snd_ctl_elem_id_malloc(&volume_id); snd_ctl_elem_id_malloc(&mute_id); snd_ctl_elem_value_malloc(&volume_ctl); snd_ctl_elem_value_malloc(&mute_ctl); snd_ctl_elem_info_malloc(&volume_info); snd_ctl_elem_id_set_interface(volume_id, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_id_set_interface(mute_id, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_id_set_name(volume_id, volume_control); snd_ctl_elem_id_set_name(mute_id, mute_control); snd_ctl_elem_value_set_id(volume_ctl, volume_id); snd_ctl_elem_value_set_id(mute_ctl, mute_id); volume_elem = snd_hctl_find_elem(hctl, volume_id); mute_elem = snd_hctl_find_elem(hctl, mute_id); snd_ctl_elem_info_set_id(volume_info, volume_id); snd_hctl_elem_info(volume_elem, volume_info); vol_min = (int)snd_ctl_elem_info_get_min(volume_info); vol_max = (int)snd_ctl_elem_info_get_max(volume_info); if (volume_elem == NULL || mute_elem == NULL) { snd_hctl_close(hctl); return EXIT_FAILURE; } struct sigaction action = {.sa_handler = &sig_handler}; sigaction(SIGUSR1, &action, NULL); if (snoop) for (;;) { if (update) { update = false; continue; } if ((exit_code = put_infos(vol_min, vol_max, volume_elem, mute_elem, volume_ctl, mute_ctl, format)) == EXIT_FAILURE) break; sleep(interval); } else exit_code = put_infos(vol_min, vol_max, volume_elem, mute_elem, volume_ctl, mute_ctl, format); snd_hctl_close(hctl); snd_ctl_elem_id_free(volume_id); snd_ctl_elem_id_free(mute_id); snd_ctl_elem_value_free(volume_ctl); snd_ctl_elem_value_free(mute_ctl); snd_ctl_elem_info_free(volume_info); return exit_code; }
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; }
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 execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type) { const char *pos; int err; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *value; snd_ctl_elem_info_t *info; unsigned int *res = NULL; snd_ctl_elem_id_malloc(&id); snd_ctl_elem_value_malloc(&value); snd_ctl_elem_info_malloc(&info); err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos); if (err < 0) goto __fail; while (*pos && isspace(*pos)) pos++; if (!*pos) { uc_error("undefined value for cset >%s<", cset); err = -EINVAL; goto __fail; } snd_ctl_elem_info_set_id(info, id); err = snd_ctl_elem_info(ctl, info); if (err < 0) goto __fail; if (type == SEQUENCE_ELEMENT_TYPE_CSET_TLV) { if (!snd_ctl_elem_info_is_tlv_writable(info)) { err = -EINVAL; goto __fail; } err = read_tlv_file(&res, pos); if (err < 0) goto __fail; err = snd_ctl_elem_tlv_write(ctl, id, res); if (err < 0) goto __fail; } else { snd_ctl_elem_value_set_id(value, id); err = snd_ctl_elem_read(ctl, value); if (err < 0) goto __fail; if (type == SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE) err = binary_file_parse(value, info, pos); else err = snd_ctl_ascii_value_parse(ctl, value, info, pos); if (err < 0) goto __fail; err = snd_ctl_elem_write(ctl, value); if (err < 0) goto __fail; } err = 0; __fail: if (id != NULL) free(id); if (value != NULL) free(value); if (info != NULL) free(info); if (res != NULL) free(res); return err; }