Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

topology: pre-processor: Introduce extends/overrides keywords for classes #268

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 172 additions & 0 deletions topology/pre-processor.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,172 @@ static int pre_process_arrays(struct tplg_pre_processor *tplg_pp, snd_config_t *
return 0;
}

static int pre_process_subtree_copy(struct tplg_pre_processor *tplg_pp, snd_config_t *curr,
snd_config_t *top)
{
snd_config_iterator_t i, next;
snd_config_t *subtrees;
int ret;

ret = snd_config_search(curr, "SubTreeCopy", &subtrees);
if (ret < 0)
return 0;

snd_config_for_each(i, next, subtrees) {
snd_config_t *n, *source_cfg, *target_cfg, *type_cfg;
snd_config_t *source_tree, *target_tree, *tmp, *subtree_cfg;
const char *id, *source_id;
const char *type = NULL;
const char *target_id = NULL;
bool override = false;

n = snd_config_iterator_entry(i);
ret = snd_config_get_id(n, &id);
if (ret < 0) {
SNDERR("Failed to get ID for subtree copy\n");
return ret;
}

/* get the type of copy ex: override/extend if set, by default override is false */
ret = snd_config_search(n, "type", &type_cfg);
if (ret >= 0) {
ret = snd_config_get_string(type_cfg, &type);
if (ret >= 0) {
if (strcmp(type, "override") && strcmp(type, "extend")) {
SNDERR("Invalid value for sub tree copy type %s\n", type);
return ret;
}

if (!strcmp(type, "override"))
override = true;
}
}

ret = snd_config_search(n, "source", &source_cfg);
if (ret < 0) {
SNDERR("failed to get source config for subtree %s\n", id);
return ret;
}

/* if the target node is not set, the subtree will be copied to current node */
ret = snd_config_search(n, "target", &target_cfg);
if (ret >= 0) {
snd_config_t *temp_target;
char *s;

ret = snd_config_get_string(target_cfg, &target_id);
if (ret < 0) {
SNDERR("Invalid target id for subtree %s\n", id);
return ret;
}

/*
* create a temporary node with target_id and merge with top to avoid
* failure in case the target node ID doesn't exist already
*/
s = tplg_snprintf("%s {}", target_id);
if (!s)
return -ENOMEM;

ret = snd_config_load_string(&temp_target, s, 0);
free(s);
if (ret < 0) {
SNDERR("Cannot create temp node with target id %s\n", target_id);
return ret;
}

ret = snd_config_merge(top, temp_target, false);
if (ret < 0) {
SNDERR("Cannot merge temp node with target id %s\n", target_id);
return ret;
}

ret = snd_config_search(top, target_id, &target_tree);
if (ret < 0) {
SNDERR("failed to get target tree %s\n", target_id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should create an empty compound for the given target path (multi id) here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@perexg I think I have addressed all your comments except this one. Im not clear why I need to create an empty compound here. I'm creating a new conf block with the source tree and the subtree merged with/without override and then I merge the merged tree to the target tree.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the target subtree in the top tree may not exist yet and it's not an error. In this case, an empty tree with target_id path should be created to work with it in the merge operation. Probably the easiest implementation is to use snd_config_load_string with "<target_id> {}" string as source and merge the result to top and do new snd_config_search for target_id / target_tree.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack, fixed now

return ret;
}
} else {
target_tree = curr;
}

/* get the source tree node */
ret = snd_config_get_string(source_cfg, &source_id);
if (ret < 0) {
SNDERR("Invalid source node id for subtree %s\n", id);
return ret;
}

ret = snd_config_search(top, source_id, &source_tree);
if (ret < 0) {
SNDERR("failed to get source tree %s\n", source_id);
return ret;
}

/* get the subtree to be merged */
ret = snd_config_search(n, "tree", &subtree_cfg);
if (ret < 0)
subtree_cfg = NULL;

/* make a temp copy of the source tree */
ret = snd_config_copy(&tmp, source_tree);
if (ret < 0) {
SNDERR("failed to copy source tree for subtreecopy %s\n", id);
return ret;
}

/* merge the current block with the source tree */
ret = snd_config_merge(tmp, subtree_cfg, override);
if (ret < 0) {
snd_config_delete(tmp);
SNDERR("Failed to merge source tree w/ subtree %s\n", id);
return ret;
}

/* merge the merged block to the target tree */
ret = snd_config_merge(target_tree, tmp, override);
if (ret < 0) {
snd_config_delete(tmp);
SNDERR("Failed to merge subtree %s w/ target\n", id);
return ret;
}
}

/* all subtree copies have been processed, remove the node */
snd_config_delete(subtrees);

return 0;
}

static int pre_process_subtree_copies(struct tplg_pre_processor *tplg_pp, snd_config_t *top,
snd_config_t *curr)
{
snd_config_iterator_t i, next;
int ret;

if (snd_config_get_type(curr) != SND_CONFIG_TYPE_COMPOUND)
return 0;

/* process subtreecopies at this node */
ret = pre_process_subtree_copy(tplg_pp, curr, top);
if (ret < 0)
return ret;

/* process subtreecopies at all child nodes */
snd_config_for_each(i, next, curr) {
snd_config_t *n;

n = snd_config_iterator_entry(i);

/* process subtreecopies at this node */
ret = pre_process_subtree_copies(tplg_pp, top, n);
if (ret < 0)
return ret;
}

return 0;
}

#endif /* version < 1.2.6 */

int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size,
Expand Down Expand Up @@ -980,6 +1146,12 @@ int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_
fprintf(stderr, "Failed to process object arrays in input config\n");
goto err;
}

err = pre_process_subtree_copies(tplg_pp, tplg_pp->input_cfg, tplg_pp->input_cfg);
if (err < 0) {
SNDERR("Failed to process subtree copies in input config\n");
goto err;
}
#endif

err = pre_process_config(tplg_pp, tplg_pp->input_cfg);
Expand Down