Esempio n. 1
0
 snd_config_for_each(i, next, conf) {
     snd_config_t *n = snd_config_iterator_entry(i);
     const char *id;
     if (snd_config_get_id(n, &id) < 0)
         continue;
     if (strcmp(id, "comment") == 0)
         continue;
     if (strcmp(id, "type") == 0)
         continue;
     if (strcmp(id, "card") == 0) {
         err = snd_config_get_integer(n, &card);
         if (err < 0) {
             err = snd_config_get_string(n, &str);
             if (err < 0)
                 return -EINVAL;
             card = snd_card_get_index(str);
             if (card < 0)
                 return card;
         }
         continue;
     }
     if (strcmp(id, "device") == 0) {
         err = snd_config_get_integer(n, &device);
         if (err < 0)
             return err;
         continue;
     }
     SNDERR("Unexpected field %s", id);
     return -EINVAL;
 }
static int config_bool(snd_config_t *n, int doit)
{
	const char *str;
	long val;
	long long lval;

	switch (snd_config_get_type(n)) {
	case SND_CONFIG_TYPE_INTEGER:
		snd_config_get_integer(n, &val);
		if (val < 0 || val > 1)
			return -1;
		return val;
	case SND_CONFIG_TYPE_INTEGER64:
		snd_config_get_integer64(n, &lval);
		if (lval < 0 || lval > 1)
			return -1;
		return (int) lval;
	case SND_CONFIG_TYPE_STRING:
		snd_config_get_string(n, &str);
		break;
	case SND_CONFIG_TYPE_COMPOUND:
		if (!force_restore || !doit)
			return -1;
		n = snd_config_iterator_entry(snd_config_iterator_first(n));
		return config_bool(n, doit);
	default:
		return -1;
	}
	if (strcmp(str, "on") == 0 || strcmp(str, "true") == 0)
		return 1;
	if (strcmp(str, "off") == 0 || strcmp(str, "false") == 0)
		return 0;
	return -1;
}
static long config_iface(snd_config_t *n)
{
	long i;
	long long li;
	snd_ctl_elem_iface_t idx; 
	const char *str;
	switch (snd_config_get_type(n)) {
	case SND_CONFIG_TYPE_INTEGER:
		snd_config_get_integer(n, &i);
		return i;
	case SND_CONFIG_TYPE_INTEGER64:
		snd_config_get_integer64(n, &li);
		return li;
	case SND_CONFIG_TYPE_STRING:
		snd_config_get_string(n, &str);
		break;
	default:
		return -1;
	}
	for (idx = 0; idx <= SND_CTL_ELEM_IFACE_LAST; idx++) {
		if (strcasecmp(snd_ctl_elem_iface_name(idx), str) == 0)
			return idx;
	}
	return -1;
}
Esempio n. 4
0
static int snd_func_iops(snd_config_t **dst,
			 snd_config_t *root,
			 snd_config_t *src,
			 snd_config_t *private_data,
			 int op)
{
	snd_config_t *n;
	snd_config_iterator_t i, next;
	const char *id;
	char *res = NULL;
	long result = 0, val;
	int idx = 0, err, hit;
	
	err = snd_config_search(src, "integers", &n);
	if (err < 0) {
		SNDERR("field integers not found");
		goto __error;
	}
	err = snd_config_evaluate(n, root, private_data, NULL);
	if (err < 0) {
		SNDERR("error evaluating integers");
		goto __error;
	}
	do {
		hit = 0;
		snd_config_for_each(i, next, n) {
			snd_config_t *n = snd_config_iterator_entry(i);
			const char *id;
			long i;
			if (snd_config_get_id(n, &id) < 0)
				continue;
			err = safe_strtol(id, &i);
			if (err < 0) {
				SNDERR("id of field %s is not an integer", id);
				err = -EINVAL;
				goto __error;
			}
			if (i == idx) {
				idx++;
				err = snd_config_get_integer(n, &val);
				if (err < 0) {
					SNDERR("invalid integer for id %s", id);
					err = -EINVAL;
					goto __error;
				}
				switch (op) {
				case 0: result += val; break;
				case 1: result *= val; break;
				}
				hit = 1;
			}
		}
	} while (hit);
	err = snd_config_get_id(src, &id);
	if (err >= 0)
		err = snd_config_imake_integer(dst, id, result);
	free(res);
      __error:
	return err;
}
Esempio n. 5
0
/**
 * \brief Gets the control interface index from a configuration node.
 * \param conf Handle to the configuration node to be parsed.
 * \return The control interface index if successful, otherwise a negative error code.
 */ 
int snd_config_get_ctl_iface(const snd_config_t *conf)
{
	long v;
	const char *str, *id;
	int err;

	err = snd_config_get_id(conf, &id);
	if (err < 0)
		return err;
	err = snd_config_get_integer(conf, &v);
	if (err >= 0) {
		if (v < 0 || v > SND_CTL_ELEM_IFACE_LAST) {
		_invalid_value:
			SNDERR("Invalid value for %s", id);
			return -EINVAL;
		}
		return v;
	}
	err = snd_config_get_string(conf, &str);
	if (err < 0) {
		SNDERR("Invalid type for %s", id);
		return -EINVAL;
	}
	err = snd_config_get_ctl_iface_ascii(str);
	if (err < 0)
		goto _invalid_value;
	return err;
}
Esempio n. 6
0
/*----------------------------------------------------------------------------
**  ALSA_DefaultDevices
**
**      Jump through Alsa style hoops to (hopefully) properly determine
**  Alsa defaults for CTL Card #, as well as for PCM Card + Device #.
**  We'll also find out if the user has set any of the environment
**  variables that specify we're to use a specific card or device.
**
**  Parameters:
**      directhw        Whether to use a direct hardware device or not;
**                      essentially switches the pcm device name from
**                      one of 'default:X' or 'plughw:X' to "hw:X"
**      defctlcard      If !NULL, will hold the ctl card number given
**                      by the ALSA config as the default
**      defpcmcard      If !NULL, default pcm card #
**      defpcmdev       If !NULL, default pcm device #
**      fixedctlcard    If !NULL, and the user set the appropriate
**                          environment variable, we'll set to the
**                          card the user specified.
**      fixedpcmcard    If !NULL, and the user set the appropriate
**                          environment variable, we'll set to the
**                          card the user specified.
**      fixedpcmdev     If !NULL, and the user set the appropriate
**                          environment variable, we'll set to the
**                          device the user specified.
**
**  Returns:  0 on success, < 0 on failure
*/
static int ALSA_DefaultDevices(int directhw,
            long *defctlcard,
            long *defpcmcard, long *defpcmdev,
            int *fixedctlcard,
            int *fixedpcmcard, int *fixedpcmdev)
{
    snd_config_t   *configp;
    char pcmsearch[256];

    ALSA_RETURN_ONFAIL(snd_config_update());

    if (defctlcard)
        if (snd_config_search(snd_config, "defaults.ctl.card", &configp) >= 0)
            snd_config_get_integer(configp, defctlcard);

    if (defpcmcard)
        if (snd_config_search(snd_config, "defaults.pcm.card", &configp) >= 0)
            snd_config_get_integer(configp, defpcmcard);

    if (defpcmdev)
        if (snd_config_search(snd_config, "defaults.pcm.device", &configp) >= 0)
            snd_config_get_integer(configp, defpcmdev);


    if (fixedctlcard)
    {
        if (snd_config_search(snd_config, "*****@*****.**", &configp) >= 0)
            ALSA_CheckEnvironment(configp, fixedctlcard);
    }

    if (fixedpcmcard)
    {
        sprintf(pcmsearch, "*****@*****.**", directhw ? "hw" : "plughw");
        if (snd_config_search(snd_config, pcmsearch, &configp) >= 0)
            ALSA_CheckEnvironment(configp, fixedpcmcard);
    }

    if (fixedpcmdev)
    {
        sprintf(pcmsearch, "*****@*****.**", directhw ? "hw" : "plughw");
        if (snd_config_search(snd_config, pcmsearch, &configp) >= 0)
            ALSA_CheckEnvironment(configp, fixedpcmdev);
    }

    return 0;
}
static int config_integer(snd_config_t *n, long *val, int doit)
{
	int err = snd_config_get_integer(n, val);
	if (err < 0 && force_restore && doit) {
		if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND)
			return err;
		n = snd_config_iterator_entry(snd_config_iterator_first(n));
		return config_integer(n, val, doit);
	}
	return err;
}
static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
			     snd_ctl_elem_info_t *info, int doit)
{
	const char *str;
	long val;
	long long lval;
	unsigned int idx, items;

	switch (snd_config_get_type(n)) {
	case SND_CONFIG_TYPE_INTEGER:
		snd_config_get_integer(n, &val);
		return val;
	case SND_CONFIG_TYPE_INTEGER64:
		snd_config_get_integer64(n, &lval);
		return (int) lval;
	case SND_CONFIG_TYPE_STRING:
		snd_config_get_string(n, &str);
		break;
	case SND_CONFIG_TYPE_COMPOUND:
		if (!force_restore || !doit)
			return -1;
		n = snd_config_iterator_entry(snd_config_iterator_first(n));
		return config_enumerated(n, handle, info, doit);
	default:
		return -1;
	}
	items = snd_ctl_elem_info_get_items(info);
	for (idx = 0; idx < items; idx++) {
		int err;
		snd_ctl_elem_info_set_item(info, idx);
		err = snd_ctl_elem_info(handle, info);
		if (err < 0) {
			error("snd_ctl_elem_info: %s", snd_strerror(err));
			return err;
		}
		if (strcmp(str, snd_ctl_elem_info_get_item_name(info)) == 0)
			return idx;
	}
	return -1;
}
Esempio n. 9
0
/**
 * \brief Creates a new File PCM
 * \param pcmp Returns created PCM handle
 * \param name Name of PCM
 * \param root Root configuration node
 * \param conf Configuration node with File PCM description
 * \param stream Stream type
 * \param mode Stream mode
 * \retval zero on success otherwise a negative error code
 * \warning Using of this function might be dangerous in the sense
 *          of compatibility reasons. The prototype might be freely
 *          changed in future.
 */
int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
		       snd_config_t *root, snd_config_t *conf, 
		       snd_pcm_stream_t stream, int mode)
{
	snd_config_iterator_t i, next;
	int err;
	snd_pcm_t *spcm;
	snd_config_t *slave = NULL, *sconf;
	const char *fname = NULL, *ifname = NULL;
	const char *format = NULL;
	long fd = -1, ifd = -1, trunc = 1;
	long perm = 0600;
	snd_config_for_each(i, next, conf) {
		snd_config_t *n = snd_config_iterator_entry(i);
		const char *id;
		if (snd_config_get_id(n, &id) < 0)
			continue;
		if (snd_pcm_conf_generic_id(id))
			continue;
		if (strcmp(id, "slave") == 0) {
			slave = n;
			continue;
		}
		if (strcmp(id, "format") == 0) {
			err = snd_config_get_string(n, &format);
			if (err < 0) {
				SNDERR("Invalid type for %s", id);
				return -EINVAL;
			}
			continue;
		}
		if (strcmp(id, "file") == 0) {
			err = snd_config_get_string(n, &fname);
			if (err < 0) {
				err = snd_config_get_integer(n, &fd);
				if (err < 0) {
					SNDERR("Invalid type for %s", id);
					return -EINVAL;
				}
			}
			continue;
		}
		if (strcmp(id, "infile") == 0) {
			err = snd_config_get_string(n, &ifname);
			if (err < 0) {
				err = snd_config_get_integer(n, &ifd);
				if (err < 0) {
					SNDERR("Invalid type for %s", id);
					return -EINVAL;
				}
			}
			continue;
		}
		if (strcmp(id, "perm") == 0) {
			err = snd_config_get_integer(n, &perm);
			if (err < 0) {
				SNDERR("Invalid type for %s", id);
				return err;
			}
			if ((perm & ~0777) != 0) {
				SNDERR("The field perm must be a valid file permission");
				return -EINVAL;
			}
			continue;
		}
		if (strcmp(id, "truncate") == 0) {
			err = snd_config_get_bool(n);
			if (err < 0)
				return -EINVAL;
			trunc = err;
			continue;
		}
		SNDERR("Unknown field %s", id);
		return -EINVAL;
	}
Esempio n. 10
0
bool CAESinkALSA::Initialize(AEAudioFormat &format, std::string &device)
{
  m_initDevice = device;
  m_initFormat = format;

  /* if we are raw, correct the data format */
  if (AE_IS_RAW(format.m_dataFormat))
  {
    m_channelLayout     = GetChannelLayout(format);
    format.m_dataFormat = AE_FMT_S16NE;
    m_passthrough       = true;
  }
  else
  {
    m_channelLayout = GetChannelLayout(format);
    m_passthrough   = false;
  }

  if (m_channelLayout.Count() == 0)
  {
    CLog::Log(LOGERROR, "CAESinkALSA::Initialize - Unable to open the requested channel layout");
    return false;
  }

  format.m_channelLayout = m_channelLayout;

  AEDeviceType devType = AEDeviceTypeFromName(device);

  std::string AESParams;
  /* digital interfaces should have AESx set, though in practice most
   * receivers don't care */
  if (m_passthrough || devType == AE_DEVTYPE_HDMI || devType == AE_DEVTYPE_IEC958)
    GetAESParams(format, AESParams);

  CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Attempting to open device \"%s\"", device.c_str());

  /* get the sound config */
  snd_config_t *config;
  snd_config_copy(&config, snd_config);

  snd_config_t *dmixRateConf;
  long dmixRate;

  if (snd_config_search(config, "defaults.pcm.dmix.rate", &dmixRateConf) < 0
      || snd_config_get_integer(dmixRateConf, &dmixRate) < 0)
    dmixRate = 48000; /* assume default */


  /* Prefer dmix for non-passthrough stereo when sample rate matches */
  if (!OpenPCMDevice(device, AESParams, m_channelLayout.Count(), &m_pcm, config, format.m_sampleRate == dmixRate && !m_passthrough))
  {
    CLog::Log(LOGERROR, "CAESinkALSA::Initialize - failed to initialize device \"%s\"", device.c_str());
    snd_config_delete(config);
    return false;
  }

  /* get the actual device name that was used */
  device = snd_pcm_name(m_pcm);
  m_device = device;

  CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Opened device \"%s\"", device.c_str());

  /* free the sound config */
  snd_config_delete(config);

  if (!InitializeHW(format) || !InitializeSW(format))
    return false;

  snd_pcm_nonblock(m_pcm, 1);
  snd_pcm_prepare (m_pcm);

  m_format              = format;
  m_formatSampleRateMul = 1.0 / (double)m_format.m_sampleRate;

  return true;
}
Esempio n. 11
0
/**
 * \brief Parse control element id from the config
 * \param conf the config tree to parse
 * \param ctl_id the pointer to store the resultant control element id
 * \param cardp the pointer to store the card index
 * \param cchannelsp the pointer to store the number of channels (optional)
 * \param hwctlp the pointer to store the h/w control flag (optional)
 * \return 0 if successful, or a negative error code
 *
 * This function parses the given config tree to retrieve the control element id
 * and the card index.  It's used by softvol.  External PCM plugins can use this
 * function for creating or assigining their controls.
 *
 * cchannelsp and hwctlp arguments are optional.  Set NULL if not necessary.
 */
int snd_pcm_parse_control_id(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp,
			     int *cchannelsp, int *hwctlp)
{
	snd_config_iterator_t i, next;
	int iface = SND_CTL_ELEM_IFACE_MIXER;
	const char *name = NULL;
	long index = 0;
	long device = -1;
	long subdevice = -1;
	int err;

	assert(ctl_id && cardp);

	*cardp = -1;
	if (cchannelsp)
		*cchannelsp = 2;
	snd_config_for_each(i, next, conf) {
		snd_config_t *n = snd_config_iterator_entry(i);
		const char *id;
		if (snd_config_get_id(n, &id) < 0)
			continue;
		if (strcmp(id, "comment") == 0)
			continue;
		if (strcmp(id, "card") == 0) {
			const char *str;
			long v;
			if ((err = snd_config_get_integer(n, &v)) < 0) {
				if ((err = snd_config_get_string(n, &str)) < 0) {
					SNDERR("Invalid field %s", id);
					goto _err;
				}
				*cardp = snd_card_get_index(str);
				if (*cardp < 0) {
					SNDERR("Cannot get index for %s", str);
					err = *cardp;
					goto _err;
				}
			} else
				*cardp = v;
			continue;
		}
		if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) {
			const char *ptr;
			if ((err = snd_config_get_string(n, &ptr)) < 0) {
				SNDERR("field %s is not a string", id);
				goto _err;
			}
			if ((err = snd_config_get_ctl_iface_ascii(ptr)) < 0) {
				SNDERR("Invalid value for '%s'", id);
				goto _err;
			}
			iface = err;
			continue;
		}
		if (strcmp(id, "name") == 0) {
			if ((err = snd_config_get_string(n, &name)) < 0) {
				SNDERR("field %s is not a string", id);
				goto _err;
			}
			continue;
		}
		if (strcmp(id, "index") == 0) {
			if ((err = snd_config_get_integer(n, &index)) < 0) {
				SNDERR("field %s is not an integer", id);
				goto _err;
			}
			continue;
		}
		if (strcmp(id, "device") == 0) {
			if ((err = snd_config_get_integer(n, &device)) < 0) {
				SNDERR("field %s is not an integer", id);
				goto _err;
			}
			continue;
		}
		if (strcmp(id, "subdevice") == 0) {
			if ((err = snd_config_get_integer(n, &subdevice)) < 0) {
				SNDERR("field %s is not an integer", id);
				goto _err;
			}
			continue;
		}
		if (cchannelsp && strcmp(id, "count") == 0) {
			long v;
			if ((err = snd_config_get_integer(n, &v)) < 0) {
				SNDERR("field %s is not an integer", id);
				goto _err;
			}
			if (v < 1 || v > 2) {
				SNDERR("Invalid count %ld", v);
				goto _err;
			}
			*cchannelsp = v;
			continue;
		}
		if (hwctlp && strcmp(id, "hwctl") == 0) {
			if ((err = snd_config_get_bool(n)) < 0) {
				SNDERR("The field %s must be a boolean type", id);
				return err;
			}
			*hwctlp = err;
			continue;
		}
		SNDERR("Unknown field %s", id);
		return -EINVAL;
	}
Esempio n. 12
0
/**
 * \brief Creates a new File PCM
 * \param pcmp Returns created PCM handle
 * \param name Name of PCM
 * \param root Root configuration node
 * \param conf Configuration node with File PCM description
 * \param stream Stream type
 * \param mode Stream mode
 * \retval zero on success otherwise a negative error code
 * \warning Using of this function might be dangerous in the sense
 *          of compatibility reasons. The prototype might be freely
 *          changed in future.
 */
int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
		       snd_config_t *root, snd_config_t *conf, 
		       snd_pcm_stream_t stream, int mode)
{
	snd_config_iterator_t i, next;
	int err;
	snd_pcm_t *spcm;
	snd_config_t *slave = NULL, *sconf;
	const char *fname = NULL, *ifname = NULL;
	const char *format = NULL;
	long fd = -1, ifd = -1;
	int perm = 0600;
	snd_config_for_each(i, next, conf) {
		snd_config_t *n = snd_config_iterator_entry(i);
		const char *id;
		if (snd_config_get_id(n, &id) < 0)
			continue;
		if (snd_pcm_conf_generic_id(id))
			continue;
		if (strcmp(id, "slave") == 0) {
			slave = n;
			continue;
		}
		if (strcmp(id, "format") == 0) {
			err = snd_config_get_string(n, &format);
			if (err < 0) {
				SNDERR("Invalid type for %s", id);
				return -EINVAL;
			}
			continue;
		}
		if (strcmp(id, "file") == 0) {
			err = snd_config_get_string(n, &fname);
			if (err < 0) {
				err = snd_config_get_integer(n, &fd);
				if (err < 0) {
					SNDERR("Invalid type for %s", id);
					return -EINVAL;
				}
			}
			continue;
		}
		if (strcmp(id, "infile") == 0) {
			err = snd_config_get_string(n, &ifname);
			if (err < 0) {
				err = snd_config_get_integer(n, &ifd);
				if (err < 0) {
					SNDERR("Invalid type for %s", id);
					return -EINVAL;
				}
			}
			continue;
		}
		if (strcmp(id, "perm") == 0) {
			char *str;
			char *endp;
			err = snd_config_get_ascii(n, &str);
			if (err < 0) {
				SNDERR("The field perm must be a valid file permission");
				return err;
			}
			if (isdigit(*str) == 0) {
				SNDERR("The field perm must be a valid file permission");
				free(str);
				return -EINVAL;
			}
			perm = strtol(str, &endp, 8);
			free(str);
			continue;
		}
		SNDERR("Unknown field %s", id);
		return -EINVAL;
	}