示例#1
0
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);
	}
}
示例#2
0
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;
}
示例#3
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);
	}
}
示例#5
0
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));
  }
示例#7
0
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;
}
示例#8
0
文件: utils.c 项目: amipro/sphone
/*
 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;
}
示例#10
0
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;
}
示例#11
0
文件: amixer.c 项目: IcaroL2ORK/pd
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;
}
示例#12
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;
}
示例#15
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;
}