@@ -42,6 +42,7 @@
#include <pulse/xmalloc.h>
#include <pulsecore/core-util.h>
#include <pulsecore/core-error.h>
+#include <pulsecore/strbuf.h>
#include "droid/conversion.h"
#include "droid/sllist.h"
@@ -70,6 +71,7 @@
/* ELEMENT_profile */
#define ELEMENT_routes "routes"
#define ELEMENT_route "route"
+#define ELEMENT_include "xi:include"
#define ATTRIBUTE_version "version"
#define ATTRIBUTE_name "name"
@@ -83,6 +85,7 @@
#define ATTRIBUTE_sink "sink"
#define ATTRIBUTE_sources "sources"
#define ATTRIBUTE_type "type"
+#define ATTRIBUTE_href "href"
#define PORT_TYPE_sink "sink"
#define PORT_TYPE_source "source"
@@ -133,6 +136,7 @@
static void parse_item(struct parser_data *data, const char *str);
static bool parse_module(struct parser_data *data, const char *element_name, const XML_Char **attributes);
static bool parse_global_configuration(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+static bool parse_module_include(struct parser_data *data, const char *element_name, const XML_Char **attributes);
static const struct element_parser element_parse_route = {
ELEMENT_route,
@@ -214,12 +218,20 @@
&element_parse_item
};
+static const struct element_parser element_parse_module_include = {
+ ELEMENT_include,
+ parse_module_include,
+ NULL,
+ &element_parse_attached_devices,
+ NULL
+};
+
static const struct element_parser element_parse_module = {
ELEMENT_module,
parse_module,
NULL,
NULL,
- &element_parse_attached_devices
+ &element_parse_module_include
};
static const struct element_parser element_parse_modules = {
@@ -309,9 +321,17 @@
struct module *next;
};
+struct includes {
+ char *href;
+ struct module *module;
+
+ struct includes *next;
+};
+
struct audio_policy_configuration {
struct global_configuration *global;
struct module *modules;
+ struct includes *includes;
};
struct parser_data {
@@ -319,7 +339,6 @@
const char *fn;
unsigned lineno;
- const struct element_parser *root;
const struct element_parser *current;
struct element_parser_stack *stack;
@@ -327,6 +346,7 @@
struct module *current_module;
struct mix_port *current_mix_port;
struct device_port *current_device_port;
+ struct includes *current_include;
};
@@ -412,9 +432,15 @@
pa_xfree(m);
}
+static void includes_free(struct includes *i) {
+ pa_assert(i);
+
+ pa_xfree(i->href);
+ pa_xfree(i);
+}
+
static void audio_policy_configuration_free(struct audio_policy_configuration *xml_config) {
struct global_configuration *global;
- struct module *m;
pa_assert(xml_config);
@@ -426,9 +452,16 @@
}
while (xml_config->modules) {
+ struct module *m;
SLLIST_STEAL_FIRST(m, xml_config->modules);
module_free(m);
- };
+ }
+
+ while (xml_config->includes) {
+ struct includes *i;
+ SLLIST_STEAL_FIRST(i, xml_config->includes);
+ includes_free(i);
+ }
pa_xfree(xml_config);
}
@@ -572,10 +605,37 @@
return true;
}
+static bool parse_module_include(struct parser_data *data, const char *element_name, const XML_Char **attributes) {
+ struct includes *i;
+ char *href = NULL;
+
+ if (!get_element_attr(data, attributes, true, ATTRIBUTE_href, &href)) {
+ pa_log("[%s:%u] Include but no href.", data->fn, data->lineno);
+ return false;
+ }
+
+ /* We ignore xpointer attribute for now and just use the module element
+ * we are currently in when parsing the included file. */
+
+ i = pa_xmalloc0(sizeof(*i));
+ i->module = data->current_module;
+ i->href = href;
+
+ SLLIST_APPEND(struct includes, data->conf->includes, i);
+
+ return true;
+}
+
static bool parse_module(struct parser_data *data, const char *element_name, const XML_Char **attributes) {
struct module *m;
char *halVersion = NULL;
+ if (data->current_include && data->current_include->module) {
+ /* We are processing included file, get our module definition from cache. */
+ data->current_module = data->current_include->module;
+ return true;
+ }
+
m = pa_xmalloc0(sizeof(*m));
get_element_attr(data, attributes, false, ATTRIBUTE_name, &m->name);
@@ -834,7 +894,7 @@
return parsed;
}
-static bool parse_file(struct parser_data *data, const char *filename) {
+static bool parse_file(struct parser_data *data, const struct element_parser *root, const char *filename) {
char buf[BUFSIZ];
FILE *f = NULL;
XML_Parser parser = NULL;
@@ -858,6 +918,8 @@
if (!data->conf)
data->conf = pa_xnew0(struct audio_policy_configuration, 1);
+ data->current = root;
+
XML_SetUserData(parser, data);
XML_SetElementHandler(parser, xml_start_element, xml_end_element);
XML_SetCharacterDataHandler(parser, xml_character_data_handler);
@@ -1020,6 +1082,31 @@
return config;
}
+/* Take base filename and relative path to filename and construct new
+ * path replacing file part from the base filename with new filename.
+ * For example, base_file="x/y/file.xml", filename="a/other.xml"
+ * result "x/y/a/other.xml"
+ */
+static char *build_path(const char *base_file, const char *filename) {
+ char *fn = NULL;
+ pa_strbuf *buf;
+ char *end;
+ int len;
+
+ pa_assert(base_file);
+ pa_assert(filename);
+
+ if ((end = strrchr(base_file, '/'))) {
+ buf = pa_strbuf_new();
+ len = end - base_file + 1;
|