Repository: microsoft/terminal
File: src/terminal/adapter/adaptDispatch.cpp (C++)

Code before:
            {
                _tabStopColumns.at(column - 1) = true;
            }
            column = 0;
        }
        else
        {
            // If we receive an unexpected character, we don't try and
            // process any more of the input - we just abort.
            return false;
        }
        return (ch != AsciiChars::ESC);
    };
}

// Routine Description:
// - DECPS - Plays a sequence of musical notes.
// Arguments:
// - params - The volume, duration, and note values to play.
void AdaptDispatch::PlaySounds(const VTParameters parameters)
{
    // First parameter is the volume, in the range 0 to 7. We multiply by
    // 127 / 7 to obtain an equivalent MIDI velocity in the range 0 to 127.
    const auto velocity = std::min(parameters.at(0).value_or(0), 7) * 127 / 7;
    // Second parameter is the duration, in the range 0 to 255. Units are
    // 1/32 of a second, so we multiply by 1000000us/32 to obtain microseconds.
    using namespace std::chrono_literals;
    const auto duration = std::min(parameters.at(1).value_or(0), 255) * 1000000us / 32;
    // The subsequent parameters are notes, in the range 0 to 25.
    parameters.subspan(2).for_each([=](const auto param) {
        // Values 1 to 25 represent the notes C5 to C7, so we add 71 to
        // obtain the equivalent MIDI note numbers (72 = C5).
        const auto noteNumber = std::min(param.value_or(0), 25) + 71;
        // But value 0 is meant to be silent, so if the note number is 71,
        // we set the velocity to 0 (i.e. no volume).
        _api.PlayMidiNote(noteNumber, noteNumber == 71 ? 0 : velocity, duration);
    });
}


Review comment (suggestion):
Thought: Xterm specifies that OSC responses are returned with the same terminator (`ST` or `BEL`) as the request that generated them. I suppose having this function affords us a much easier way to find/fix all occurrences of us being out of spec :)

>         XTerm accepts either BEL  or ST  for terminating OSC
>         sequences, and when returning information, uses the same
>         terminator used in a query.  While the latter is preferred,
>         the former is supported for legacy applications:
>         o   Although documented in the changes for X.V10R4 (December
>             1986), BEL  as a string terminator dates from X11R4
>             (December 1989).
>         o   Since XFree86-3.1.2Ee (August 1996), xterm has accepted ST
>             (the documented string terminator in ECMA-48).



Code after:
            column = 0;
        }
        else
        {
            // If we receive an unexpected character, we don't try and
            // process any more of the input - we just abort.
            return false;
        }
        return (ch != AsciiChars::ESC);
    };
}

void AdaptDispatch::_ReturnCsiResponse(const std::wstring_view response) const
{
    const auto csi = _terminalInput.GetInputMode(TerminalInput::Mode::SendC1) ? L"\x9B" : L"\x1B[";
    _api.ReturnResponse(fmt::format(FMT_COMPILE(L"{}{}"), csi, response));
}

void AdaptDispatch::_ReturnDcsResponse(const std::wstring_view response) const
{
    const auto dcs = _terminalInput.GetInputMode(TerminalInput::Mode::SendC1) ? L"\x90" : L"\x1BP";
    const auto st = _terminalInput.GetInputMode(TerminalInput::Mode::SendC1) ? L"\x9C" : L"\x1B\\";
    _api.ReturnResponse(fmt::format(FMT_COMPILE(L"{}{}{}"), dcs, response, st));
}

void AdaptDispatch::_ReturnOscResponse(const std::wstring_view response) const
{
    const auto osc = _terminalInput.GetInputMode(TerminalInput::Mode::SendC1) ? L"\x9D" : L"\x1B]";
    const auto st = _terminalInput.GetInputMode(TerminalInput::Mode::SendC1) ? L"\x9C" : L"\x1B\\";
    _api.ReturnResponse(fmt::format(FMT_COMPILE(L"{}{}{}"), osc, response, st));
}

// Routine Description:
// - DECPS - Plays a sequence of musical notes.
// Arguments:
// - params - The volume, duration, and note values to play.
void AdaptDispatch::PlaySounds(const VTParameters parameters)
{
    // First parameter is the volume, in the range 0 to 7. We multiply by
    // 127 / 7 to obtain an equivalent MIDI velocity in the range 0 to 127.
    const auto velocity = std::min(parameters.at(0).value_or(0), 7) * 127 / 7;
    // Second parameter is the duration, in the range 0 to 255. Units are
    // 1/32 of a second, so we multiply by 1000000us/32 to obtain microseconds.
    using namespace std::chrono_literals;
    const auto duration = std::min(parameters.at(1).value_or(0), 255) * 1000000us / 32;
    // The subsequent parameters are notes, in the range 0 to 25.
    parameters.subspan(2).for_each([=](const auto param) {
        // Values 1 to 25 represent the notes C5 to C7, so we add 71 to
        // obtain the equivalent MIDI note numbers (72 = C5).
        const auto noteNumber = std::min(param.value_or(0), 25) + 71;
        // But value 0 is meant to be silent, so if the note number is 71,