You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Send the DCS passthrough sequence to the engine #7316
I've beening trying to make this work like what we did with OSC, that is collecting all the pass through character into a string named _dcsDataString and send it to engine when the DCS sequences terminates. The implementation is straight forward:
voidStateMachine::_ActionDcsPassThrough(constwchar_t wch)
{
_trace.TraceOnAction(L"DcsPassThrough");
_trace.TraceOnExecute(wch);
if (!_isDcsPassingThrough)
{
// The first character being passed through is the "final character", which combined with intermediates// defines the functionality of the DCS sequence. Here we treat it as part of the identifier.
_identifier.AddIntermediate(wch);
_isDcsPassingThrough = true;
}
else
{
_dcsDataString.push_back(wch);
}
}
But when dealing with large sixel image outputs, the string collecting itself takes seconds to complete. I'm thinking maybe a direct pass through to the engine should help with the performance.
My assumption was that the parsing for the DCS command string would be handled in the dispatch classes - I don't think the state machine should need to know about all the different sequence formats. Once it's identified the operation from the final character, I think it should be streaming the command string straight through to the adapter so it can be processed immediately as the data arrives.
In the case of Sixel graphics, this would allow the adapter to render the image straight to the screen as the pixels are received. I think there are other DCS sequences, like music operations, that would have similar requirements. And yes, OSC might fall into this category too.
For the majority of simple operations that don't require streaming, though, there could be a default handler that just gathers everything up in a string, and passes that along once the string terminator is received.
So what I had in mind was that the state machine would dispatch any of the command string sequences (DCS, APC, etc.) as soon as it received the "final" character and could generate a full VTID. The dispatch method would not be able to process the command at that point, but based on the id it would return an instance of a consumer class. The state machine would save a copy of that, and pass on every subsequent character to that consumer until it received a string terminator, or some kind of error/abort state. At that point it would notify the consumer that it had reached the end of message and the command could be processed (or aborted).
If the dispatcher didn't recognize the VTID, it could return a kind of null consumer that would just ignore everything without wasting memory collecting bytes that were never going to be used. If it was a simple operation that just wanted the final string, it could return a generic consumer that would handle all the data collection automatically (similar to what is currently done with OSC), and then trigger a specified callback function/lambda with the final content. But for something like Sixel, which needs full control of the data, it would return a custom consumer class that could process each character as it was received.
OSC could potentially also follow this pattern, although the initial dispatching is more complicated because of the way the commands are identified. So perhaps that's something that's best left for a follow-up PR, once we've got the basic concept working. Another reason being it's going require a bunch of refactoring of all the existing OSC sequences, since the command string parsing would now be in the dispatch class rather than the state machine.
Chester Liu (@skyline75489) Just as a follow up to your comment on the Sixel issue, I want to be clear that this DCS pass through thing is not something I'm currently working on, in case you were waiting on me. If nobody else takes it on, I will likely get to it eventually, because there are a whole lot of DCS operations I'd love to implement. But for now I've got other issues I want to tackle first. I also figured you're probably the best person to handle this at the moment, because the Sixel requirements will probably be key to shaping the API.
James Holderness (@j4james) I hear you loud and clear. Thanks for inspiring comments both in this thread and in #448 . I was stuck with my unfinished sixel implementation about a month ago, so I moved on to those OSC things. I think I'll give DCS/sixel another try when I have time.
Chester Liu (@skyline75489) If you aren't working on this, I'd be happy to take it on now. I've started working on the "soft fonts" feature (issue #9164) which has similar DCS requirements to Sixel, so I thought it would make a good test case for this.
For the "consumer class" that I mentioned in my initial proposal above, I realised we could probably get by with a simple std::function<bool(wchar_t)>, and then the dispatch handler could just return a lambda without necessarily requiring a separate class.
The way it would work, the state machine would just pass through all the characters from the DCS string to the returned function, and could indicate the end of the sequence by sending through an ST character. If we need to differentiate an abort from a successful termination, we could also send through a CAN control character, but I'm not sure that's really necessary.
Activity
zadjii-msft commentedon Aug 17, 2020
I'm yanking triage off this one because yea duh we should do this. Thanks for filing!
skyline75489 commentedon Aug 30, 2020
I've beening trying to make this work like what we did with OSC, that is collecting all the pass through character into a string named
_dcsDataStringand send it to engine when the DCS sequences terminates. The implementation is straight forward:But when dealing with large sixel image outputs, the string collecting itself takes seconds to complete. I'm thinking maybe a direct pass through to the engine should help with the performance.
skyline75489 commentedon Sep 15, 2020
Note from James Holderness (@j4james) originally written in #7578 (comment)
j4james commentedon Sep 15, 2020
So what I had in mind was that the state machine would dispatch any of the command string sequences (DCS, APC, etc.) as soon as it received the "final" character and could generate a full VTID. The dispatch method would not be able to process the command at that point, but based on the id it would return an instance of a consumer class. The state machine would save a copy of that, and pass on every subsequent character to that consumer until it received a string terminator, or some kind of error/abort state. At that point it would notify the consumer that it had reached the end of message and the command could be processed (or aborted).
If the dispatcher didn't recognize the VTID, it could return a kind of null consumer that would just ignore everything without wasting memory collecting bytes that were never going to be used. If it was a simple operation that just wanted the final string, it could return a generic consumer that would handle all the data collection automatically (similar to what is currently done with OSC), and then trigger a specified callback function/lambda with the final content. But for something like Sixel, which needs full control of the data, it would return a custom consumer class that could process each character as it was received.
OSC could potentially also follow this pattern, although the initial dispatching is more complicated because of the way the commands are identified. So perhaps that's something that's best left for a follow-up PR, once we've got the basic concept working. Another reason being it's going require a bunch of refactoring of all the existing OSC sequences, since the command string parsing would now be in the dispatch class rather than the state machine.
j4james commentedon Oct 10, 2020
Chester Liu (@skyline75489) Just as a follow up to your comment on the Sixel issue, I want to be clear that this DCS pass through thing is not something I'm currently working on, in case you were waiting on me. If nobody else takes it on, I will likely get to it eventually, because there are a whole lot of DCS operations I'd love to implement. But for now I've got other issues I want to tackle first. I also figured you're probably the best person to handle this at the moment, because the Sixel requirements will probably be key to shaping the API.
skyline75489 commentedon Oct 11, 2020
James Holderness (@j4james) I hear you loud and clear. Thanks for inspiring comments both in this thread and in #448 . I was stuck with my unfinished sixel implementation about a month ago, so I moved on to those OSC things. I think I'll give DCS/sixel another try when I have time.
j4james commentedon Feb 18, 2021
Chester Liu (@skyline75489) If you aren't working on this, I'd be happy to take it on now. I've started working on the "soft fonts" feature (issue #9164) which has similar
DCSrequirements to Sixel, so I thought it would make a good test case for this.For the "consumer class" that I mentioned in my initial proposal above, I realised we could probably get by with a simple
std::function<bool(wchar_t)>, and then the dispatch handler could just return a lambda without necessarily requiring a separate class.The way it would work, the state machine would just pass through all the characters from the
DCSstring to the returned function, and could indicate the end of the sequence by sending through anSTcharacter. If we need to differentiate an abort from a successful termination, we could also send through aCANcontrol character, but I'm not sure that's really necessary.skyline75489 commentedon Feb 18, 2021
Introduce a mechanism for passing through DCS data strings (#9307)