static void change_iec958_elem_members(struct elem_set_trial *trial,
				       snd_ctl_elem_value_t *elem_data)
{
	snd_aes_iec958_t data;

	/* To suppress GCC warnings. */
	trial->element_count = 1;

	snd_ctl_elem_value_get_iec958(elem_data, &data);
	/* This is an arbitrary number. */
	data.pad = 10;
	snd_ctl_elem_value_set_iec958(elem_data, &data);
}
예제 #2
0
파일: amixer.c 프로젝트: zhouguanying/null
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;
}
예제 #3
0
/* 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;
}