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; }
/** * 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; }