Esempio n. 1
0
gchar *
gst_alsa_find_device_name (GstObject * obj, const gchar * device,
    snd_pcm_t * handle, snd_pcm_stream_t stream)
{
  gchar *ret = NULL;

  if (device != NULL) {
    gchar *dev, *comma;
    gint devnum;

    GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device);

    /* only want name:card bit, but not devices and subdevices */
    dev = g_strdup (device);
    if ((comma = strchr (dev, ','))) {
      *comma = '\0';
      devnum = atoi (comma + 1);
      ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream);
    }
    g_free (dev);
  }

  if (ret == NULL && handle != NULL) {
    snd_pcm_info_t *info;

    GST_LOG_OBJECT (obj, "Trying to get device name from open handle");
    snd_pcm_info_malloc (&info);
    snd_pcm_info (handle, info);
    ret = g_strdup (snd_pcm_info_get_name (info));
    snd_pcm_info_free (info);
  }

  GST_LOG_OBJECT (obj, "Device name for device '%s': %s",
      GST_STR_NULL (device), GST_STR_NULL (ret));

  return ret;
}
Esempio n. 2
0
void bg_alsa_create_card_parameters(bg_parameter_info_t * ret,
                                    int record)
  {
  snd_ctl_card_info_t *info;
  snd_ctl_t *handle;
  snd_pcm_info_t *pcminfo;
  snd_pcm_stream_t stream;
  int err;
  int card, dev;

  stream = record ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK;
  
  ret->name      = gavl_strdup("card");
  ret->long_name = gavl_strdup(TRS("Card"));
  ret->type = BG_PARAMETER_STRINGLIST;

  snd_ctl_card_info_malloc(&info);

  card = -1;
  if (snd_card_next(&card) < 0 || card < 0)
    {
    bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No soundcards found");
    return;
    }
  
  /* Default is always supported */
  ret->val_default.val_str = gavl_strdup("default");
  append_card(ret, gavl_strdup("default"),
              gavl_strdup(TRS("Default")));
  
  while (card >= 0)
    {
    char name[32];
    sprintf(name, "hw:%d", card);
    if ((err = snd_ctl_open(&handle, name, 0)) < 0)
      {
      bg_log(BG_LOG_ERROR, LOG_DOMAIN,
             "control open failed (%i): %s",
             card, snd_strerror(err));
      goto next_card;
      }
    if ((err = snd_ctl_card_info(handle, info)) < 0)
      {
      bg_log(BG_LOG_ERROR, LOG_DOMAIN,
             "control hardware info failed (%i): %s",
             card, snd_strerror(err));
      snd_ctl_close(handle);
      goto next_card;
      }
    dev = -1;

    while (1)
      {
      char * name, *label;
      snd_pcm_info_malloc(&pcminfo);
      if (snd_ctl_pcm_next_device(handle, &dev)<0)
        {
        bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_ctl_pcm_next_device failed");
        snd_pcm_info_free(pcminfo);
        break;
        }
      if (dev < 0)
        {
        snd_pcm_info_free(pcminfo);
        break;
        }
      snd_pcm_info_set_device(pcminfo, dev);
      snd_pcm_info_set_subdevice(pcminfo, 0);
      snd_pcm_info_set_stream(pcminfo, stream);
      if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0)
        {
        if (err != -ENOENT)
          bg_log(BG_LOG_ERROR, LOG_DOMAIN,
                 "control digital audio info failed (%i): %s",
                 card, snd_strerror(err));
        snd_pcm_info_free(pcminfo);
        continue;
        }
      name = bg_sprintf("hw:%d,%d", card, dev);
      label = gavl_strdup(snd_pcm_info_get_name(pcminfo));
      append_card(ret, name, label);
      snd_pcm_info_free(pcminfo);
      }
    snd_ctl_close(handle);
    
    next_card:
    if (snd_card_next(&card) < 0)
      break;
    }
  snd_ctl_card_info_free(info);
  
  }
// for each ALSA device, call iterator. userData is passed to the iterator
// returns total number of iterations
int iteratePCMDevices(DeviceIteratorPtr iterator, void* userData) {
    int count = 0;
    int subdeviceCount;
    int card, dev, subDev;
    char devname[16];
    int err;
    snd_ctl_t *handle;
    snd_pcm_t *pcm;
    snd_pcm_info_t* pcminfo;
    snd_ctl_card_info_t *cardinfo, *defcardinfo = NULL;
    UINT32 deviceID;
    int doContinue = TRUE;

    snd_pcm_info_malloc(&pcminfo);
    snd_ctl_card_info_malloc(&cardinfo);

    // 1st try "default" device
    err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
                       SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
    if (err < 0) {
        // try with the other direction
        err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
                           SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
    }
    if (err < 0) {
        ERROR1("ERROR: snd_pcm_open (\"default\"): %s\n", snd_strerror(err));
    } else {
        err = snd_pcm_info(pcm, pcminfo);
        snd_pcm_close(pcm);
        if (err < 0) {
            ERROR1("ERROR: snd_pcm_info (\"default\"): %s\n",
                    snd_strerror(err));
        } else {
            // try to get card info
            card = snd_pcm_info_get_card(pcminfo);
            if (card >= 0) {
                sprintf(devname, ALSA_HARDWARE_CARD, card);
                if (snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK) >= 0) {
                    if (snd_ctl_card_info(handle, cardinfo) >= 0) {
                        defcardinfo = cardinfo;
                    }
                    snd_ctl_close(handle);
                }
            }
            // call callback function for the device
            if (iterator != NULL) {
                doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, pcminfo,
                                         defcardinfo, userData);
            }
            count++;
        }
    }

    // iterate cards
    card = -1;
    while (doContinue) {
        if (snd_card_next(&card) < 0) {
            break;
        }
        if (card < 0) {
            break;
        }
        sprintf(devname, ALSA_HARDWARE_CARD, card);
        TRACE1("Opening alsa device \"%s\"...\n", devname);
        err = snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK);
        if (err < 0) {
            ERROR2("ERROR: snd_ctl_open, card=%d: %s\n",
                    card, snd_strerror(err));
        } else {
            err = snd_ctl_card_info(handle, cardinfo);
            if (err < 0) {
                ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n",
                        card, snd_strerror(err));
            } else {
                dev = -1;
                while (doContinue) {
                    if (snd_ctl_pcm_next_device(handle, &dev) < 0) {
                        ERROR0("snd_ctl_pcm_next_device\n");
                    }
                    if (dev < 0) {
                        break;
                    }
                    snd_pcm_info_set_device(pcminfo, dev);
                    snd_pcm_info_set_subdevice(pcminfo, 0);
                    snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
                    err = snd_ctl_pcm_info(handle, pcminfo);
                    if (err == -ENOENT) {
                        // try with the other direction
                        snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
                        err = snd_ctl_pcm_info(handle, pcminfo);
                    }
                    if (err < 0) {
                        if (err != -ENOENT) {
                            ERROR2("ERROR: snd_ctl_pcm_info, card=%d: %s",
                                    card, snd_strerror(err));
                        }
                    } else {
                        subdeviceCount = needEnumerateSubdevices(ALSA_PCM) ?
                            snd_pcm_info_get_subdevices_count(pcminfo) : 1;
                        if (iterator!=NULL) {
                            for (subDev = 0; subDev < subdeviceCount; subDev++) {
                                deviceID = encodeDeviceID(card, dev, subDev);
                                doContinue = (*iterator)(deviceID, pcminfo,
                                                         cardinfo, userData);
                                count++;
                                if (!doContinue) {
                                    break;
                                }
                            }
                        } else {
                            count += subdeviceCount;
                        }
                    }
                } // of while(doContinue)
            }
            snd_ctl_close(handle);
        }
    }
    snd_ctl_card_info_free(cardinfo);
    snd_pcm_info_free(pcminfo);
    return count;
}
Esempio n. 4
0
static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
{
    const char *main_prefix = "plughw:";
    snd_ctl_t *handle;
    snd_ctl_card_info_t *info;
    snd_pcm_info_t *pcminfo;
    int card, err, dev;
    DevMap entry;

    clear_devlist(DeviceList);

    snd_ctl_card_info_malloc(&info);
    snd_pcm_info_malloc(&pcminfo);

    AL_STRING_INIT(entry.name);
    AL_STRING_INIT(entry.device_name);
    al_string_copy_cstr(&entry.name, alsaDevice);
    al_string_copy_cstr(&entry.device_name, GetConfigValue(NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
                                                           "device" : "capture", "default"));
    VECTOR_PUSH_BACK(*DeviceList, entry);

    card = -1;
    if((err=snd_card_next(&card)) < 0)
        ERR("Failed to find a card: %s\n", snd_strerror(err));
    ConfigValueStr(NULL, "alsa", prefix_name(stream), &main_prefix);
    while(card >= 0)
    {
        const char *card_prefix = main_prefix;
        const char *cardname, *cardid;
        char name[256];

        snprintf(name, sizeof(name), "hw:%d", card);
        if((err = snd_ctl_open(&handle, name, 0)) < 0)
        {
            ERR("control open (hw:%d): %s\n", card, snd_strerror(err));
            goto next_card;
        }
        if((err = snd_ctl_card_info(handle, info)) < 0)
        {
            ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err));
            snd_ctl_close(handle);
            goto next_card;
        }

        cardname = snd_ctl_card_info_get_name(info);
        cardid = snd_ctl_card_info_get_id(info);

        snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid);
        ConfigValueStr(NULL, "alsa", name, &card_prefix);

        dev = -1;
        while(1)
        {
            const char *device_prefix = card_prefix;
            const char *devname;
            char device[128];

            if(snd_ctl_pcm_next_device(handle, &dev) < 0)
                ERR("snd_ctl_pcm_next_device failed\n");
            if(dev < 0)
                break;

            snd_pcm_info_set_device(pcminfo, dev);
            snd_pcm_info_set_subdevice(pcminfo, 0);
            snd_pcm_info_set_stream(pcminfo, stream);
            if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
                if(err != -ENOENT)
                    ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err));
                continue;
            }

            devname = snd_pcm_info_get_name(pcminfo);

            snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
            ConfigValueStr(NULL, "alsa", name, &device_prefix);

            snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
                        cardname, devname, cardid, dev);
            snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d",
                        device_prefix, cardid, dev);

            TRACE("Got device \"%s\", \"%s\"\n", name, device);
            AL_STRING_INIT(entry.name);
            AL_STRING_INIT(entry.device_name);
            al_string_copy_cstr(&entry.name, name);
            al_string_copy_cstr(&entry.device_name, device);
            VECTOR_PUSH_BACK(*DeviceList, entry);
        }
        snd_ctl_close(handle);
    next_card:
        if(snd_card_next(&card) < 0) {
            ERR("snd_card_next failed\n");
            break;
        }
    }

    snd_pcm_info_free(pcminfo);
    snd_ctl_card_info_free(info);
}
Esempio n. 5
0
static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count)
{
    const char *main_prefix = "plughw:";
    snd_ctl_t *handle;
    int card, err, dev, idx;
    snd_ctl_card_info_t *info;
    snd_pcm_info_t *pcminfo;
    DevMap *DevList;

    snd_ctl_card_info_malloc(&info);
    snd_pcm_info_malloc(&pcminfo);

    DevList = malloc(sizeof(DevMap) * 1);
    DevList[0].name = strdup(alsaDevice);
    DevList[0].device = strdup(GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
                                                      "device" : "capture", "default"));
    idx = 1;

    card = -1;
    if((err=snd_card_next(&card)) < 0)
        ERR("Failed to find a card: %s\n", snd_strerror(err));
    ConfigValueStr("alsa", prefix_name(stream), &main_prefix);
    while(card >= 0)
    {
        const char *card_prefix = main_prefix;
        const char *cardname, *cardid;
        char name[256];

        snprintf(name, sizeof(name), "hw:%d", card);
        if((err = snd_ctl_open(&handle, name, 0)) < 0)
        {
            ERR("control open (hw:%d): %s\n", card, snd_strerror(err));
            goto next_card;
        }
        if((err = snd_ctl_card_info(handle, info)) < 0)
        {
            ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err));
            snd_ctl_close(handle);
            goto next_card;
        }

        cardname = snd_ctl_card_info_get_name(info);
        cardid = snd_ctl_card_info_get_id(info);

        snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid);
        ConfigValueStr("alsa", name, &card_prefix);

        dev = -1;
        while(1)
        {
            const char *devname;
            void *temp;

            if(snd_ctl_pcm_next_device(handle, &dev) < 0)
                ERR("snd_ctl_pcm_next_device failed\n");
            if(dev < 0)
                break;

            snd_pcm_info_set_device(pcminfo, dev);
            snd_pcm_info_set_subdevice(pcminfo, 0);
            snd_pcm_info_set_stream(pcminfo, stream);
            if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
                if(err != -ENOENT)
                    ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err));
                continue;
            }

            temp = realloc(DevList, sizeof(DevMap) * (idx+1));
            if(temp)
            {
                const char *device_prefix = card_prefix;
                char device[128];

                DevList = temp;
                devname = snd_pcm_info_get_name(pcminfo);

                snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
                ConfigValueStr("alsa", name, &device_prefix);

                snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
                         cardname, devname, cardid, dev);
                snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d",
                         device_prefix, cardid, dev);

                TRACE("Got device \"%s\", \"%s\"\n", name, device);
                DevList[idx].name = strdup(name);
                DevList[idx].device = strdup(device);
                idx++;
            }
        }
        snd_ctl_close(handle);
    next_card:
        if(snd_card_next(&card) < 0) {
            ERR("snd_card_next failed\n");
            break;
        }
    }

    snd_pcm_info_free(pcminfo);
    snd_ctl_card_info_free(info);

    *count = idx;
    return DevList;
}
static GList *
gst_alsa_get_device_list (snd_pcm_stream_t stream)
{
  snd_ctl_t *handle;
  int card, dev;
  snd_ctl_card_info_t *info;
  snd_pcm_info_t *pcminfo;
  gboolean mixer = (stream == -1);
  GList *list = NULL;

  if (stream == -1)
    stream = 0;

  snd_ctl_card_info_malloc (&info);
  snd_pcm_info_malloc (&pcminfo);
  card = -1;

  if (snd_card_next (&card) < 0 || card < 0) {
    /* no soundcard found */
    GST_WARNING ("No soundcard found");
    goto beach;
  }

  while (card >= 0) {
    gchar name[32];

    g_snprintf (name, sizeof (name), "hw:%d", card);
    if (snd_ctl_open (&handle, name, 0) < 0) {
      goto next_card;
    }
    if (snd_ctl_card_info (handle, info) < 0) {
      snd_ctl_close (handle);
      goto next_card;
    }

    if (mixer) {
      list = g_list_append (list, g_strdup (name));
    } else {
      dev = -1;
      while (1) {
        gchar *gst_device;

        snd_ctl_pcm_next_device (handle, &dev);

        if (dev < 0)
          break;
        snd_pcm_info_set_device (pcminfo, dev);
        snd_pcm_info_set_subdevice (pcminfo, 0);
        snd_pcm_info_set_stream (pcminfo, stream);
        if (snd_ctl_pcm_info (handle, pcminfo) < 0) {
          continue;
        }

        gst_device = g_strdup_printf ("hw:%d,%d", card, dev);
        list = g_list_append (list, gst_device);
      }
    }
    snd_ctl_close (handle);
  next_card:
    if (snd_card_next (&card) < 0) {
      break;
    }
  }

beach:
  snd_ctl_card_info_free (info);
  snd_pcm_info_free (pcminfo);

  return list;
}
Esempio n. 7
0
/* returns the card name when the device number is unknown or -1 */
static gchar *
gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard,
    gint device_num, snd_pcm_stream_t stream)
{
  snd_ctl_card_info_t *info = NULL;
  snd_ctl_t *ctl = NULL;
  gchar *ret = NULL;
  gint dev = -1;

  GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num);

  if (snd_ctl_open (&ctl, devcard, 0) < 0)
    return NULL;

  snd_ctl_card_info_malloc (&info);
  if (snd_ctl_card_info (ctl, info) < 0)
    goto done;

  if (device_num != -1) {
    while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) {
      if (dev == device_num) {
        snd_pcm_info_t *pcminfo;

        snd_pcm_info_malloc (&pcminfo);
        snd_pcm_info_set_device (pcminfo, dev);
        snd_pcm_info_set_subdevice (pcminfo, 0);
        snd_pcm_info_set_stream (pcminfo, stream);
        if (snd_ctl_pcm_info (ctl, pcminfo) < 0) {
          snd_pcm_info_free (pcminfo);
          break;
        }

        ret = (gchar *) snd_pcm_info_get_name (pcminfo);
        if (ret) {
          ret = g_strdup (ret);
          GST_LOG_OBJECT (obj, "name from pcminfo: %s", ret);
        }
        snd_pcm_info_free (pcminfo);
        if (ret)
          break;
      }
    }
  }

  if (ret == NULL) {
    char *name = NULL;
    gint card;

    GST_LOG_OBJECT (obj, "trying card name");
    card = snd_ctl_card_info_get_card (info);
    snd_card_get_name (card, &name);
    ret = g_strdup (name);
    free (name);
  }

done:
  snd_ctl_card_info_free (info);
  snd_ctl_close (ctl);

  return ret;
}
Esempio n. 8
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;
}
Esempio n. 9
0
std::vector<ALSAInput::Source> ALSAInput::GetSourceList() {
	std::vector<Source> list;

	/*
	This code is based on the ALSA device detection code used in PortAudio. I just ported it to C++ and improved it a bit.
	All credit goes to the PortAudio devs, they saved me a lot of time :).
	*/

	// these ALSA plugins are blacklisted because they are always defined but rarely useful
	// 'pulse' is also blacklisted because the native PulseAudio backend is more reliable
	std::vector<std::string> plugin_blacklist = {
		"cards", "default", "sysdefault", "hw", "plughw", "plug", "dmix", "dsnoop", "shm", "tee", "file", "null",
		"front", "rear", "center_lfe", "side", "surround40", "surround41", "surround50", "surround51", "surround71",
		"iec958", "spdif", "hdmi", "modem", "phoneline", "pulse",
	};
	std::sort(plugin_blacklist.begin(), plugin_blacklist.end());

	// the 'default' PCM must be first, so add it explicitly
	list.push_back(Source("default", "Default source"));

	Logger::LogInfo("[ALSAInput::GetSourceList] " + Logger::tr("Generating source list ..."));

	snd_ctl_card_info_t *alsa_card_info = NULL;
	snd_pcm_info_t *alsa_pcm_info = NULL;
	snd_ctl_t *alsa_ctl = NULL;

	try {

		// allocate card and PCM info structure
		if(snd_ctl_card_info_malloc(&alsa_card_info) < 0) {
			throw std::bad_alloc();
		}
		if(snd_pcm_info_malloc(&alsa_pcm_info) < 0) {
			throw std::bad_alloc();
		}

		// update the ALSA configuration
		snd_config_update_free_global();
		if(snd_config_update() < 0) {
			Logger::LogError("[ALSAInput::GetSourceList] " + Logger::tr("Error: Could not update ALSA configuration!"));
			throw ALSAException();
		}

		// find all PCM plugins (by parsing the config file)
		snd_config_t *alsa_config_pcms = NULL;
		if(snd_config_search(snd_config, "pcm", &alsa_config_pcms) == 0) {
			snd_config_iterator_t i, next;
			snd_config_for_each(i, next, alsa_config_pcms) {
				snd_config_t *alsa_config_pcm = snd_config_iterator_entry(i);

				// get the name
				const char *id = NULL;
				if(snd_config_get_id(alsa_config_pcm, &id) < 0 || id == NULL)
					continue;
				std::string plugin_name = id;

				// ignore the plugin if it is blacklisted
				if(std::binary_search(plugin_blacklist.begin(), plugin_blacklist.end(), plugin_name))
					continue;

				// try to get the description
				std::string plugin_description;
				snd_config_t *alsa_config_description = NULL;
				if(snd_config_search(alsa_config_pcm, "hint.description", &alsa_config_description) == 0) {
					const char *str = NULL;
					if(snd_config_get_string(alsa_config_description, &str) >= 0 && str != NULL) {
						plugin_description = str;
					}
				}

				// if there is no description, ignore it, because it's probably not meant to be used
				if(plugin_description.empty())
					continue;

				// if there is no description, use the type instead
				/*if(plugin_description.empty()) {
					snd_config_t *alsa_config_type = NULL;
					if(snd_config_search(alsa_config_pcm, "type", &alsa_config_type) >= 0) {
						const char *str = NULL;
						if(snd_config_get_string(alsa_config_type, &str) >= 0 && str != NULL) {
							plugin_description = std::string(str) + " plugin";
						}
					}
				}*/

				// add to list
				Logger::LogInfo("[ALSAInput::GetSourceList] " + Logger::tr("Found plugin: [%1] %2").arg(QString::fromStdString(plugin_name)).arg(QString::fromStdString(plugin_description)));
				list.push_back(Source(plugin_name, plugin_description));

			}
		}
Esempio n. 10
0
File: alsa.c Progetto: 9heart/DT3
static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count)
{
    snd_ctl_t *handle;
    int card, err, dev, idx;
    snd_ctl_card_info_t *info;
    snd_pcm_info_t *pcminfo;
    DevMap *DevList;
    char name[1024];

    snd_ctl_card_info_malloc(&info);
    snd_pcm_info_malloc(&pcminfo);

    card = -1;
    if((err=snd_card_next(&card)) < 0)
        ERR("Failed to find a card: %s\n", snd_strerror(err));

    DevList = malloc(sizeof(DevMap) * 1);
    DevList[0].name = strdup("ALSA Default");
    DevList[0].card = NULL;
    DevList[0].dev = 0;
    idx = 1;
    while(card >= 0)
    {
        sprintf(name, "hw:%d", card);
        if((err = snd_ctl_open(&handle, name, 0)) < 0)
        {
            ERR("control open (%i): %s\n", card, snd_strerror(err));
            goto next_card;
        }
        if((err = snd_ctl_card_info(handle, info)) < 0)
        {
            ERR("control hardware info (%i): %s\n", card, snd_strerror(err));
            snd_ctl_close(handle);
            goto next_card;
        }

        dev = -1;
        while(1)
        {
            const char *cname, *dname, *cid;
            void *temp;

            if(snd_ctl_pcm_next_device(handle, &dev) < 0)
                ERR("snd_ctl_pcm_next_device failed\n");
            if(dev < 0)
                break;

            snd_pcm_info_set_device(pcminfo, dev);
            snd_pcm_info_set_subdevice(pcminfo, 0);
            snd_pcm_info_set_stream(pcminfo, stream);
            if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
                if(err != -ENOENT)
                    ERR("control digital audio info (%i): %s\n", card, snd_strerror(err));
                continue;
            }

            temp = realloc(DevList, sizeof(DevMap) * (idx+1));
            if(temp)
            {
                DevList = temp;
                cname = snd_ctl_card_info_get_name(info);
                dname = snd_pcm_info_get_name(pcminfo);
                cid = snd_ctl_card_info_get_id(info);
                snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
                         cname, dname, cid, dev);
                DevList[idx].name = strdup(name);
                DevList[idx].card = strdup(cid);
                DevList[idx].dev = dev;
                idx++;
            }
        }
        snd_ctl_close(handle);
    next_card:
        if(snd_card_next(&card) < 0) {
            ERR("snd_card_next failed\n");
            break;
        }
    }

    snd_pcm_info_free(pcminfo);
    snd_ctl_card_info_free(info);

    *count = idx;
    return DevList;
}