Пример #1
0
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);
  }
}
Пример #2
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;
}
Пример #3
0
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;
}
Пример #4
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;
}
Пример #5
0
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;
}
Пример #6
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;
}
Пример #7
0
/**
 * \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;
}
Пример #8
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;
}
Пример #9
0
/**
* alsa dumy codec controls interface
*/
int dummy_alsa_control_raw(char * id_string , long vol, int rw, long * value){
    int err;
    snd_hctl_t *hctl;
    snd_ctl_elem_id_t *id;
    snd_hctl_elem_t *elem;
    snd_ctl_elem_value_t *control;
    snd_ctl_elem_info_t *info;
    snd_ctl_elem_type_t type;
    unsigned int idx = 0, count;
    long tmp, min, max;
    char dev[10] = {0};
    int card = alsa_get_aml_card();
    int port = alsa_get_spdif_port();

    adec_print("card = %d, port = %d\n", card, port);
    sprintf(dev, "hw:%d,%d", (card >= 0) ? card : 0, (port >= 0) ? port : 0);

    if ((err = snd_hctl_open(&hctl, dev, 0)) < 0) {
        printf("Control %s open error: %s\n", dev, snd_strerror(err));
        return err;
    }
    if (err = snd_hctl_load(hctl)< 0) {
        printf("Control %s open error: %s\n", dev, snd_strerror(err));
        return err;
    }
    snd_ctl_elem_id_alloca(&id);
    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
    snd_ctl_elem_id_set_name(id, id_string);
    elem = snd_hctl_find_elem(hctl, id);
    snd_ctl_elem_value_alloca(&control);
    snd_ctl_elem_value_set_id(control, id);
    snd_ctl_elem_info_alloca(&info);
    if ((err = snd_hctl_elem_info(elem, info)) < 0) {
        printf("Control %s snd_hctl_elem_info error: %s\n", dev, snd_strerror(err));
        return err;
    }
    count = snd_ctl_elem_info_get_count(info);
    type = snd_ctl_elem_info_get_type(info);

    for (idx = 0; idx < count; idx++) {
        switch (type) {
            case SND_CTL_ELEM_TYPE_BOOLEAN:
                if(rw){
                    tmp = 0;
                    if (vol >= 1) {
                        tmp = 1;
                    }
                    snd_ctl_elem_value_set_boolean(control, idx, tmp);
                    err = snd_hctl_elem_write(elem, control);
                }else
            *value = snd_ctl_elem_value_get_boolean(control, idx);
            break;
            case SND_CTL_ELEM_TYPE_INTEGER:
                if(rw){
            min = snd_ctl_elem_info_get_min(info);
            max = snd_ctl_elem_info_get_max(info);
                    if ((vol >= min) && (vol <= max))
                        tmp = vol;
            else if (vol < min)
                        tmp = min;
                    else if (vol > max)
                        tmp = max;
                    snd_ctl_elem_value_set_integer(control, idx, tmp);
                    err = snd_hctl_elem_write(elem, control);
                }else
                *value = snd_ctl_elem_value_get_integer(control, idx);
            break;
            default:
                printf("?");
            break;
        }
        if (err < 0){
            printf ("control%s access error=%s,close control device\n", dev, snd_strerror(err));
            snd_hctl_close(hctl);
            return err;
        }
    }

    return 0;
}
Пример #10
0
/**************************************************************************
 * 			ALSA_CheckSetVolume		[internal]
 *
 *  Helper function for Alsa volume queries.  This tries to simplify
 * the process of managing the volume.  All parameters are optional
 * (pass NULL to ignore or not use).
 *  Return values are MMSYSERR_NOERROR on success, or !0 on failure;
 * error codes are normalized into the possible documented return
 * values from waveOutGetVolume.
 */
int ALSA_CheckSetVolume(snd_hctl_t *hctl, int *out_left, int *out_right,
            int *out_min, int *out_max, int *out_step,
            int *new_left, int *new_right)
{
    int rc = MMSYSERR_NOERROR;
    int value_count = 0;
    snd_hctl_elem_t *           elem = NULL;
    snd_ctl_elem_info_t *       eleminfop = NULL;
    snd_ctl_elem_value_t *      elemvaluep = NULL;
    snd_ctl_elem_id_t *         elemidp = NULL;
    const char *names[] = {"PCM Playback Volume", "Line Playback Volume", NULL};
    const char **name;


#define EXIT_ON_ERROR(f,txt,exitcode) do \
{ \
    int err; \
    if ( (err = (f) ) < 0) \
    { \
	ERR(txt " failed: %s\n", snd_strerror(err)); \
        rc = exitcode; \
        goto out; \
    } \
} while(0)

    if (! hctl)
        return MMSYSERR_NOTSUPPORTED;

    /* Allocate areas to return information about the volume */
    EXIT_ON_ERROR(snd_ctl_elem_id_malloc(&elemidp), "snd_ctl_elem_id_malloc", MMSYSERR_NOMEM);
    EXIT_ON_ERROR(snd_ctl_elem_value_malloc (&elemvaluep), "snd_ctl_elem_value_malloc", MMSYSERR_NOMEM);
    EXIT_ON_ERROR(snd_ctl_elem_info_malloc (&eleminfop), "snd_ctl_elem_info_malloc", MMSYSERR_NOMEM);
    snd_ctl_elem_id_clear(elemidp);
    snd_ctl_elem_value_clear(elemvaluep);
    snd_ctl_elem_info_clear(eleminfop);

    /* Setup and find an element id that exactly matches the characteristic we want
    ** FIXME:  It is probably short sighted to hard code and fixate on PCM Playback Volume */

    for( name = names; *name; name++ )
    {
	snd_ctl_elem_id_set_name(elemidp, *name);
	snd_ctl_elem_id_set_interface(elemidp, SND_CTL_ELEM_IFACE_MIXER);
	elem = snd_hctl_find_elem(hctl, elemidp);
	if (elem)
	{
	    /* Read and return volume information */
	    EXIT_ON_ERROR(snd_hctl_elem_info(elem, eleminfop), "snd_hctl_elem_info", MMSYSERR_NOTSUPPORTED);
	    value_count = snd_ctl_elem_info_get_count(eleminfop);
	    if (out_min || out_max || out_step)
	    {
		if (!snd_ctl_elem_info_is_readable(eleminfop))
		{
		    ERR("snd_ctl_elem_info_is_readable returned false; cannot return info\n");
		    rc = MMSYSERR_NOTSUPPORTED;
		    goto out;
		}

		if (out_min)
		    *out_min = snd_ctl_elem_info_get_min(eleminfop);

		if (out_max)
		    *out_max = snd_ctl_elem_info_get_max(eleminfop);

		if (out_step)
		    *out_step = snd_ctl_elem_info_get_step(eleminfop);
	    }

	    if (out_left || out_right)
	    {
		EXIT_ON_ERROR(snd_hctl_elem_read(elem, elemvaluep), "snd_hctl_elem_read", MMSYSERR_NOTSUPPORTED);

		if (out_left)
		    *out_left = snd_ctl_elem_value_get_integer(elemvaluep, 0);

		if (out_right)
		{
		    if (value_count == 1)
			*out_right = snd_ctl_elem_value_get_integer(elemvaluep, 0);
		    else if (value_count == 2)
			*out_right = snd_ctl_elem_value_get_integer(elemvaluep, 1);
		    else
		    {
			ERR("Unexpected value count %d from snd_ctl_elem_info_get_count while getting volume info\n", value_count);
			rc = -1;
			goto out;
		    }
		}
	    }

	    /* Set the volume */
	    if (new_left || new_right)
	    {
		EXIT_ON_ERROR(snd_hctl_elem_read(elem, elemvaluep), "snd_hctl_elem_read", MMSYSERR_NOTSUPPORTED);
		if (new_left)
		    snd_ctl_elem_value_set_integer(elemvaluep, 0, *new_left);
		if (new_right)
		{
		    if (value_count == 1)
			snd_ctl_elem_value_set_integer(elemvaluep, 0, *new_right);
		    else if (value_count == 2)
			snd_ctl_elem_value_set_integer(elemvaluep, 1, *new_right);
		    else
		    {
			ERR("Unexpected value count %d from snd_ctl_elem_info_get_count while setting volume info\n", value_count);
			rc = -1;
			goto out;
		    }
		}

		EXIT_ON_ERROR(snd_hctl_elem_write(elem, elemvaluep), "snd_hctl_elem_write", MMSYSERR_NOTSUPPORTED);
	    }

	    break;
	}
    }

    if( !*name )
    {
        ERR("Could not find '{PCM,Line} Playback Volume' element\n");
        rc = MMSYSERR_NOTSUPPORTED;
    }


#undef EXIT_ON_ERROR

out:

    if (elemvaluep)
        snd_ctl_elem_value_free(elemvaluep);
    if (eleminfop)
        snd_ctl_elem_info_free(eleminfop);
    if (elemidp)
        snd_ctl_elem_id_free(elemidp);

    return rc;
}
Пример #11
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;
}