Open Firionus opened 2 years ago
Come to think of it, I guess the easier way to handle this issue is to understand "next ChannelFunction" as "next ChannelFunction according to XML order".
So. second proposal for the "DMXTo" issue:
Change Description of ChannelFunction XML-attribute DMXFrom to:
Start DMX value; The end DMX value is calculated as DMXFrom - 1 of the next channel function in XML order, or, if the next channel function has a smaller DMXFrom, the maximum value of the DMX channel. Default value: "0/1".
To make it even more clear that ChannelFunction order has an influence, I'd propose adjusting parts of the LogicalChannel, too:
As children the logical channel has an ordered list of a channel function.
The expressiveness of this is even better than what I suggested above, since one isn't bound to the rule that each DMXFrom value has to occur a certain amount of time for each ModeMaster group.
I like this second version a lot more :joy: It's much less text, much less complicated and probably closer to what you meant originally?
PS: Ensuring the Logical Channels are mutually exclusive are a different topic, really... Shall I move it to a new issue?
Even this is not a low hanging fruit, I want to take this on our list for the meetings.
I think the Builder prevents this now.
Start DMX value; The end DMX value is calculated as a DMXFrom of the next channel function – 1 or the maximum value of the DMX channel. Default value: "0/1".
We need to define more what the next channel function is. This is depended on:
Is your feature request related to a problem? Please describe.
According to DIN SPEC 15800:2020-07, ChannelFunctions only specify DMXFrom. The value of DMXTo has to be calculated as DMXFrom - 1 of the "next" ChannelFunction or the maximum value of the DMXChannel. Unfortunately, no restrictions are made in the standard that would make the "next" ChannelFunction uniquely identifiable under all circumstances.
Consider this DMXChannel from a GDTF file produced by the Builder (without any errors):
Besides the fact that these attributes don't make any sense, please note that both "Dimmer 1" and "Pan 2" start at 0 and "Tilt 3" starts at 128. It is now undefined whether "Dimmer 1" or "Pan 2" should stop at 127 and which should stop at 255.
In fact whether you make "Dimmer 1" or "Pan 2" stop at 127 in the builder, in each case the same output is produced, just with a different order of the ChannelFunctions (in the above GDTF, "Dimmer 1" ended at 255 and "Pan 2" ended at 127).
The problem is further exacerbated once you include ModeMaster dependencies because you can create cases where DMXTo changes depending on the value of another channel. Consider this pseudo-GDTF:
Here, when the ModeMaster "base_Control1" is 0-126, "Dimmer 1" goes from 0 to 255. If "base_Control1" is in 127-255, "Dimmer" goes from 0 to 126.
I don't know about you, but I want the standard to forbid dynamic changes of DMXTo depending on the values of other channels. If that is a needed behavior, just repeat the ChannelFunctions with the appropriate ModeMasters.
Describe the solution you'd like
As we've seen, the extremely lenient GDTF standard makes it easy for implementations like the Builder to produce output that is hard to interpret. Therefore, I would like a clear spec that only allows GDTF files that are easy to interpret.
Clean Slate Approach
If we were to start with a clean slate, I would suggest completely dropping the "LogicalChannel" in favor of a "ModeMasterContainer" that has ModeMaster/ModeFrom/ModeTo as XML-attributes, which would be dropped from ChannelFunction. The ModeMasterContainer would require its children ChannelFunctions to have a unique DMXFrom value.
ModeMasterContainers with duplicate ModeMaster/ModeFrom/ModeTo would be allowed for cases where two attributes need to change depending on the value of a DMXChannel.
The XML-attributes of LogicalChannel would be moved to another child of DMXChannel, named "DMXBehaviors" containing children of type "DMXBehavior". DMXBehaviors has an XML-attribute ModeMaster which can only be a DMXChannel, not a ChannelFunction, to ensure mutual exclusion of the DMXBehaviors. If ModeMaster is not present, only one child DMXBehavior must be present. Each DMXBehavior specifies a DMXFrom and DMXChangeTimeLimit/Master/etc. There must be at least one DMXBehavior with DMXFrom=0 and no two DMXBehaviors can have the same DMXFrom.
This clean slate approach has the following desirable characteristics:
Getting the benefits without changes to the file format
One can get all of the above benefits without changing the file format.
First, we need to somehow enforce mutual exclusivity of the LogicalChannels because its XML-attributes can only be active one at a time. Mutual exclusivity is worded in the standard, but the formulation is muddy and there is no described mechanism that provides this mutual exclusivity. So, I'll propose such a mechanism:
If we put this in the standard, we should remember to also define what "active" means for a ChannelFunction. I consider a ChannelFunction active if:
Unfortunately, the above mechanism introduces a dependence on the order of the LogicalChannels, but I don't see a better way to do it.
Next, we'd have to introduce a mechanism that ensures DMX ranges never intersect, yet allows multiple attributes to be controlled:
Since DMXFrom occurs the same amount of times in each of these groups, it is always clear what the "next" ChannelFunction DMXFrom is. For example, it would be okay to have 2 ChannelFunctions in a group starting at 0 and 2 ChannelFunctions starting at 128. It would not be okay to have 2 ChannelFunctions in a group start at 0 and only 1 ChannelFunction starting at 128, because then we'd have the same situation as in the beginning of this post.
Note that I did not require a ChannelFunction with DMXFrom=0 in each group, so that the groups don't have to form fully filled DMX ranges. While the builder does not allow empty parts at the bottom of the range, the GDTF standard itself currently allows this and I don't see a reason to change that.
The charming characteristic of the above solution is that there are no changes to the file format, only the semantics and validation change from an undefined to a more restricted state. Of course, these changes might still invalidate some old files or require changes to existing code.
I'm looking forward to your comments on my proposal and would love to hear how you've tackled this issue so far in your code bases :smiley: