-
Notifications
You must be signed in to change notification settings - Fork 139
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
Conversation
Thanks @ranj063 |
Could we just work with whole configuration blocks? This feature may be useful for all config parts. Like:
|
@perexg since we'd like to keep the new sub class definitions in separate conf files, the uniqueid might be problematic. But maybe if I make it an array like below, it might be OK. Also, can I retain both the extends/overrides type for the subtreecopy to achieve both pipeline extensions and pipeline widget insertion+reordering for Pipeline classes. For other configs, this could work as a generic config block copy. |
Unique ID may be like "Pipeline-mixout-efx-dai-copier-playback" so I don't see a problem here. Using [] (arrays) will assign IDs from the index range (0 ... ) automatically.
The merge type for the new tree update may be specified using a field - I proposed |
Not sure I follow what the uniqueID is, it looks redundant with the target in the suggested example?
|
@perexg I have modified the PR to define the Subtreecopy keyword now. Please let me know what you think of this. Thanks! |
It's just up to the user to create a unique ID scheme. You can compose any string. If you use one key for multiple configs, the last value is used:
The result is that |
topology/pre-processor.c
Outdated
return ret; | ||
} | ||
|
||
ret = snd_config_merge(tmp, n, override); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this required? Only source_tree
should be merged to the target_tree
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably a missing lookup for the tree
field before.
topology/pre-processor.c
Outdated
snd_config_t *subtrees; | ||
int ret; | ||
|
||
ret = snd_config_search(curr, "Subtreecopy", &subtrees); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have already special blocks like CombineArrays
, thus using upper cases in the middle is fine. I would prefer SubtreeCopy
or SubTreeCopy
here or even TreeCopy
or ConfigCopy
(may be a good alternative).
topology/pre-processor.c
Outdated
/* get the type of copy ex: override/extend */ | ||
ret = snd_config_search(n, "type", &type_cfg); | ||
if (ret < 0) { | ||
SNDERR("failed to get type for subtree %s\n", id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would keep the type field as optional with a default (override
?).
Ok, I would remove all class.pipeline specific code. It is not required IMHO. See:
|
|
||
ret = snd_config_search(top, target_id, &target_tree); | ||
if (ret < 0) { | ||
SNDERR("failed to get target tree %s\n", target_id); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack, fixed now
BTW: I like your nested examples. They show the power for the subtree copying. |
topology/pre-processor.c
Outdated
} | ||
|
||
/* delete the source/target/type nodes */ | ||
ret = snd_config_delete(source_cfg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
snd_config_delete(subtrees)
does this job for the whole processed SubTreeCopy
block. I think that this step is extra.
topology/pre-processor.c
Outdated
return ret; | ||
|
||
if (type) { | ||
ret = snd_config_delete(type_cfg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recheck all error paths and the resource deallocation in this function. There are many resource leaks IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only 2 resources allocated are for the temporary target ID and the temporary node while merging the source tree. I think I have freed both of them in the error paths.
The |
@perexg Sorry for the delay, it was a long weekend in the US. I removed the target/source/type fields from the SUbTreeCOpy node explicitly so that if those fields are valid in the subtree being copied, they will be retained. |
Yes, but you cannot override them later then. In my eyes, it would be better to keep the source subtree completely separated (although it requires a new tab level). |
@perexg I'm not sure I'm following your comment. Could you please elaborate what you're thinking here? |
Do not mix SubTreeCopy configuration with the added/modified tree.
Vs. your current implementation:
|
Thanks @perexg. Updated now |
@perexg can I please bother you to have another look at this PR? I've addressed all your comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, do the last little change. Thank you.
topology/pre-processor.c
Outdated
/* get the subtree to be merged. create an empty tree if it dosen't exist */ | ||
ret = snd_config_search(n, "tree", &subtree_cfg); | ||
if (ret < 0) { | ||
char *s; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's too overkill. Just assign subtree_cfg = NULL
here. The function snd_config_merge
does nothing when src == NULL
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@perexg sorry for the delay. I was out on vacation. Fixed now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@perexg Could I please request to have a look at the PR again?
Introduce a new kyword "SubTreeCopy" for extneding existing conf nodes with additional nodes. This feature is useful for extending previous pipeline class definitions with the addition of one or more widgets without having to duplicate everything in the new class definition. For example: Consider a pipeline class definition as below. Note that only the widgets & routes are shown here. Class.Pipeline.mixout-gain-dai-copier-playback { Object.Widget { mixout."1" {} dai-copier."1" {} gain."1" {} pipeline."1" {} } Object.Base { !route [ { source mixout.$index.1 sink gain.$index.1 } ] } } If we want to extend this pipeline with the addition of an eqiir/eqfir, we can create a SubTreeCopy node with type extend as follows: Class.Pipeline.mixout-gain-eqiir-eqfir-dai-copier-playback { SubTreeCopy.baseclass { source "Class.Pipeline.mixout-gain-dai-copier-playback" type extend tree { Object.Widget { eqiir.1 {} eqfir.1 {} } Object.Base { !route [ { source gain.$index.1 sink eqiir.$index.1 } { source eqiir.$index.1 sink eqfir.$index.1 } ] } } } } Note that the target is left undefined, which means that the newly created subtree will be merged to the parent node that contains the "SubTreeCopy" node i.e. in this case Class.Pipeline.mixout-gain-eqiir-eqfir-dai-copier-playback". But if we want to modify an existing pipeline class while modifying the order of widgets and/or inserting new widgets, we should use the type "override" instead. This allows for adding new widgets to the list of widgets in the base class definition while also allowing overriding the routes to allow inserting the new widgets and reordering the widgets in the base class. For example, if we want to add a drc widget between the gain and the eqiir modules in the above class, we can do the following: Class.Pipeline.mixout-efx-dai-copier-playback { # This copy will override all widgets/routes in the base class SubTreeCopy.baseclass { source "Class.Pipeline.mixout-gain-eqiir-eqfir-dai-copier-playback" target "Class.Pipeline" type override tree { Object.Widget { drc.1 {} } Object.Base { !route [ { source mixout.$index.1 sink gain.$index.1 } { source gain.$index.1 sink drc.$index.1 } { source drc.$index.1 sink eqiir.$index.1 } { source eqiir.$index.1 sink eqfir.$index.1 } ] } } } # Explicitly copy the widgets from the base class now SubTreeCopy.widgets { source "Class.Pipeline.mixout-gain-eqiir-eqfir-dai-copier-playback.Object.Widget" target "Class.Pipeline.mixout-efx-dai-copier-playback.Object.Widget" } } Signed-off-by: Ranjani Sridharan <[email protected]>
@perexg Could you please have a look at this again? This will help us update our SOF topologies. Thanks! |
Introduce a new keyword "Subtreecopy" for extending existing conf nodes
with additional nodes. This feature is useful for extending previous
pipeline class definitions with the addition of one or more widgets
without having to duplicate everything in the new class definition.
For example: Consider a pipeline class definition as below. Note that
only the widgets & routes are shown here.
If we want to extend this pipeline with the addition of an eqiir/eqfir,
we can create a Subtreecopy node with type extend as follows:
But if we want to modify an existing pipeline class while modifying the
order of widgets and/or inserting new widgets, we should use the type
"override" instead. This allows for adding new widgets to the list of
widgets in the base class definition while also allowing overriding the
routes to allow inserting the new widgets and reordering the widgets in
the base class. For example, if we want to add a drc widget between the
gain and the eqiir modules in the above class, we can do the following:
Note that the routes array contains all the routes in the new subtreecopy definition.
This subtreecopy feature can also be used to copy normal config blocks
without having the need to duplicate information.
For example, if all the widgets in a pipeline support the same audio
formats, we can define it as follows:
The subtreecopy node in each widget ensures that the pipeline formats
are applied to all widgets without the need for duplicating them for
each widget.
Link: thesofproject/sof#9082