Commit 5e103b5f authored by Max Kellermann's avatar Max Kellermann

filter/route: merge the two loops, one-pass parsing

parent de5be62d
......@@ -48,10 +48,9 @@
#include "FilterInternal.hxx"
#include "FilterRegistry.hxx"
#include "pcm/PcmBuffer.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <algorithm>
#include <assert.h>
......@@ -135,88 +134,70 @@ RouteFilter::Configure(const config_param &param, Error &error) {
* dynamic realloc() instead of one count run and one malloc().
*/
gchar **tokens;
int number_of_copies;
// A cowardly default, just passthrough stereo
const char *const routes = param.GetBlockValue("routes", "0>0, 1>1");
std::fill_n(sources, MAX_CHANNELS, -1);
min_input_channels = 0;
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;
// Squeeze whitespace
g_strstrip(tokens[c]);
// A cowardly default, just passthrough stereo
const char *routes = param.GetBlockValue("routes", "0>0, 1>1");
while (true) {
routes = strchug_fast(routes);
char *endptr;
const unsigned source = strtoul(routes, &endptr, 10);
endptr = strchug_fast(endptr);
if (endptr == routes || *endptr != '>') {
error.Set(config_domain,
"Malformed 'routes' specification");
return false;
}
// Split the a>b string into source and destination
sd = g_strsplit(tokens[c], ">", 2);
if (g_strv_length(sd) != 2) {
if (source >= MAX_CHANNELS) {
error.Format(config_domain,
"Invalid copy around %d in routes spec: %s",
param.line, tokens[c]);
g_strfreev(sd);
g_strfreev(tokens);
"Invalid source channel number: %u",
source);
return false;
}
unsigned source = strtoul(sd[0], NULL, 10);
unsigned dest = strtoul(sd[1], NULL, 10);
// Keep track of the highest channel numbers seen
// as either in- or outputs
if (source >= min_input_channels)
min_input_channels = source + 1;
if (dest >= min_output_channels)
min_output_channels = dest + 1;
g_strfreev(sd);
}
routes = strchug_fast(endptr + 1);
if (!audio_valid_channel_count(min_output_channels)) {
g_strfreev(tokens);
error.Format(config_domain,
"Invalid number of output channels requested: %d",
min_output_channels);
return false;
}
// 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;
unsigned dest = strtoul(routes, &endptr, 10);
endptr = strchug_fast(endptr);
if (endptr == routes) {
error.Set(config_domain,
"Malformed 'routes' specification");
return false;
}
// Split the a>b string into source and destination
sd = g_strsplit(tokens[c], ">", 2);
if (g_strv_length(sd) != 2) {
if (dest >= MAX_CHANNELS) {
error.Format(config_domain,
"Invalid copy around %d in routes spec: %s",
param.line, tokens[c]);
g_strfreev(sd);
g_strfreev(tokens);
"Invalid destination channel number: %u",
dest);
return false;
}
unsigned source = strtoul(sd[0], NULL, 10);
unsigned dest = strtoul(sd[1], NULL, 10);
if (dest >= min_output_channels)
min_output_channels = dest + 1;
sources[dest] = source;
g_strfreev(sd);
}
routes = endptr;
if (*routes == 0)
break;
if (*routes != ',') {
error.Set(config_domain,
"Malformed 'routes' specification");
return false;
}
g_strfreev(tokens);
++routes;
}
return true;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment