bool
audio_check_sample_format(enum sample_format sample_format, GError **error_r)
{
	if (!audio_valid_sample_format(sample_format)) {
		g_set_error(error_r, audio_format_quark(), 0,
			    "Invalid sample format: %u", sample_format);
		return false;
	}

	return true;
}
bool
audio_check_channel_count(unsigned channels, GError **error_r)
{
	if (!audio_valid_channel_count(channels)) {
		g_set_error(error_r, audio_format_quark(), 0,
			    "Invalid channel count: %u", channels);
		return false;
	}

	return true;
}
bool
audio_check_sample_rate(unsigned long sample_rate, GError **error_r)
{
	if (!audio_valid_sample_rate(sample_rate)) {
		g_set_error(error_r, audio_format_quark(), 0,
			    "Invalid sample rate: %lu", sample_rate);
		return false;
	}

	return true;
}
Example #4
0
/**
 * Parse the "routes" section, a string on the form
 *  a>b, c>d, e>f, ...
 * where a... are non-unique, non-negative integers
 * and input channel a gets copied to output channel b, etc.
 * @param param the configuration block to read
 * @param filter a route_filter whose min_channels and sources[] to set
 * @return true on success, false on error
 */
static bool
route_filter_parse(const struct config_param *param,
		   struct route_filter *filter,
		   GError **error_r) {

	/* TODO:
	 * With a more clever way of marking "don't copy to output N",
	 * This could easily be merged into a single loop with some
	 * dynamic g_realloc() instead of one count run and one g_malloc().
	 */

	gchar **tokens;
	int number_of_copies;

	// A cowardly default, just passthrough stereo
	const char *routes =
		config_get_block_string(param, "routes", "0>0, 1>1");

	filter->min_input_channels = 0;
	filter->min_output_channels = 0;

	tokens = g_strsplit(routes, ",", 255);
	number_of_copies = g_strv_length(tokens);

	// Start by figuring out a few basic things about the routing set
	for (int c=0; c<number_of_copies; ++c) {

		// String and int representations of the source/destination
		gchar **sd;
		int source, dest;

		// Squeeze whitespace
		g_strstrip(tokens[c]);

		// Split the a>b string into source and destination
		sd = g_strsplit(tokens[c], ">", 2);
		if (g_strv_length(sd) != 2) {
			g_set_error(error_r, config_quark(), 1,
				"Invalid copy around %d in routes spec: %s",
				param->line, tokens[c]);
			g_strfreev(sd);
			g_strfreev(tokens);
			return false;
		}

		source = strtol(sd[0], NULL, 10);
		dest = strtol(sd[1], NULL, 10);

		// Keep track of the highest channel numbers seen
		// as either in- or outputs
		if (source >= filter->min_input_channels)
			filter->min_input_channels = source + 1;
		if (dest   >= filter->min_output_channels)
			filter->min_output_channels = dest + 1;

		g_strfreev(sd);
	}

	if (!audio_valid_channel_count(filter->min_output_channels)) {
		g_strfreev(tokens);
		g_set_error(error_r, audio_format_quark(), 0,
			    "Invalid number of output channels requested: %d",
			    filter->min_output_channels);
		return false;
	}

	// Allocate a map of "copy nothing to me"
	filter->sources =
		g_malloc(filter->min_output_channels * sizeof(signed char));

	for (int i=0; i<filter->min_output_channels; ++i)
		filter->sources[i] = -1;

	// Run through the spec again, and save the
	// actual mapping output <- input
	for (int c=0; c<number_of_copies; ++c) {

		// String and int representations of the source/destination
		gchar **sd;
		int source, dest;

		// Split the a>b string into source and destination
		sd = g_strsplit(tokens[c], ">", 2);
		if (g_strv_length(sd) != 2) {
			g_set_error(error_r, config_quark(), 1,
				"Invalid copy around %d in routes spec: %s",
				param->line, tokens[c]);
			g_strfreev(sd);
			g_strfreev(tokens);
			return false;
		}

		source = strtol(sd[0], NULL, 10);
		dest = strtol(sd[1], NULL, 10);

		filter->sources[dest] = source;

		g_strfreev(sd);
	}

	g_strfreev(tokens);

	return true;
}