aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/filter/RouteFilterPlugin.cxx103
1 files changed, 42 insertions, 61 deletions
diff --git a/src/filter/RouteFilterPlugin.cxx b/src/filter/RouteFilterPlugin.cxx
index fe843b73e..c0b0be242 100644
--- a/src/filter/RouteFilterPlugin.cxx
+++ b/src/filter/RouteFilterPlugin.cxx
@@ -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;
}