Skip to content

Commit 680bb02

Browse files
Merge pull request #530 from microsoft/pete-dev
Fix issue with extra 00 running status going through service from WinMM
2 parents b752a4f + f11c8bc commit 680bb02

File tree

6 files changed

+282
-193
lines changed

6 files changed

+282
-193
lines changed

src/api/Client/WinMM/MidiSrvPort.cpp

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ CMidiPort::Callback(_In_ PVOID data, _In_ UINT size, _In_ LONGLONG position, LON
463463
BYTE inProgressMidiMessage[3]{ 0 }; // status, data 1, data 2
464464
BYTE countMidiMessageBytesReceived = 0;
465465

466-
BYTE immediateSingleByteMessage{ 0 }; // real time or other single-byte message that could interrupt the in-progress message
466+
BYTE prioritySingleByteMessage{ 0 }; // real time or other single-byte message that could interrupt the in-progress message
467467

468468
LPMIDIHDR buffer{ nullptr };
469469

@@ -479,7 +479,7 @@ CMidiPort::Callback(_In_ PVOID data, _In_ UINT size, _In_ LONGLONG position, LON
479479
// do not add it to the inProgressMidiMessage or any buffer even though
480480
// this shouldn't happen with midisrv-supplied message data
481481

482-
immediateSingleByteMessage = *callbackData;
482+
prioritySingleByteMessage = *callbackData;
483483
}
484484
else if (!m_IsInSysex)
485485
{
@@ -488,7 +488,10 @@ CMidiPort::Callback(_In_ PVOID data, _In_ UINT size, _In_ LONGLONG position, LON
488488
{
489489
// we're not in SysEx mode, but this byte was provided
490490
// so we'll send it anyway
491-
immediateSingleByteMessage = *callbackData;
491+
// Convert from the QPC time to the number of ticks elapsed from the start time.
492+
DWORD ticks = (DWORD)(((position - startTime) / m_qpcFrequency) * 1000.0);
493+
DWORD_PTR midiMessage = *callbackData;
494+
WinmmClientCallback(MIM_ERROR, midiMessage, ticks);
492495
}
493496
else if (MIDI_BYTE_IS_SYSEX_START_STATUS(*callbackData))
494497
{
@@ -539,10 +542,9 @@ CMidiPort::Callback(_In_ PVOID data, _In_ UINT size, _In_ LONGLONG position, LON
539542
{
540543
// Handle a data byte, and not sysex.
541544

542-
if (countMidiMessageBytesReceived > 0 && countMidiMessageBytesReceived < 3)
545+
if (countMidiMessageBytesReceived >= 1 && countMidiMessageBytesReceived < 3)
543546
{
544-
inProgressMidiMessage[countMidiMessageBytesReceived] = *callbackData;
545-
countMidiMessageBytesReceived++;
547+
inProgressMidiMessage[countMidiMessageBytesReceived++] = *callbackData;
546548
}
547549
else
548550
{
@@ -551,9 +553,9 @@ CMidiPort::Callback(_In_ PVOID data, _In_ UINT size, _In_ LONGLONG position, LON
551553
// to do that. We could even put in a reg setting to control this behavior.
552554

553555
// Convert from the QPC time to the number of ticks elapsed from the start time.
554-
DWORD ticks = (DWORD)(((position - startTime) / m_qpcFrequency) * 1000.0);
555-
UINT32 midiMessage = *callbackData;
556-
WinmmClientCallback(MIM_ERROR, midiMessage, ticks);
556+
//DWORD ticks = (DWORD)(((position - startTime) / m_qpcFrequency) * 1000.0);
557+
//DWORD_PTR midiMessage = *callbackData;
558+
//WinmmClientCallback(MIM_ERROR, midiMessage, ticks);
557559
}
558560
}
559561
}
@@ -621,40 +623,46 @@ CMidiPort::Callback(_In_ PVOID data, _In_ UINT size, _In_ LONGLONG position, LON
621623

622624
}
623625

624-
if (immediateSingleByteMessage > 0)
626+
if (MIDI_BYTE_IS_STATUS_BYTE(prioritySingleByteMessage))
625627
{
626628
// Convert from the QPC time to the number of ticks elapsed from the start time.
627629
DWORD ticks = (DWORD)(((position - startTime) / m_qpcFrequency) * 1000.0);
628-
UINT32 midiMessage = *callbackData;
630+
DWORD_PTR midiMessage{ prioritySingleByteMessage };
629631
WinmmClientCallback(MIM_DATA, midiMessage, ticks);
630632

631-
immediateSingleByteMessage = 0;
633+
prioritySingleByteMessage = 0;
632634
}
633635

634636
// do we have a complete non-SysEx message to send? If so, send it
635-
if (countMidiMessageBytesReceived == 3 && MIDI_MESSAGE_IS_THREE_BYTES(inProgressMidiMessage[0]) ||
636-
countMidiMessageBytesReceived == 2 && MIDI_MESSAGE_IS_TWO_BYTES(inProgressMidiMessage[0]) ||
637-
countMidiMessageBytesReceived == 1 && MIDI_MESSAGE_IS_ONE_BYTE(inProgressMidiMessage[0]))
637+
if (countMidiMessageBytesReceived > 0)
638638
{
639-
// Convert from the QPC time to the number of ticks elapsed from the start time.
640-
DWORD ticks = (DWORD)(((position - startTime) / m_qpcFrequency) * 1000.0);
641-
UINT32 midiMessage{ inProgressMidiMessage[0] };
642-
643-
if (MIDI_MESSAGE_IS_TWO_BYTES(inProgressMidiMessage[0]) || MIDI_MESSAGE_IS_THREE_BYTES(inProgressMidiMessage[0]))
639+
if (countMidiMessageBytesReceived == 3 && MIDI_MESSAGE_IS_THREE_BYTES(inProgressMidiMessage[0]) ||
640+
countMidiMessageBytesReceived == 2 && MIDI_MESSAGE_IS_TWO_BYTES(inProgressMidiMessage[0]) ||
641+
countMidiMessageBytesReceived == 1 && MIDI_MESSAGE_IS_ONE_BYTE(inProgressMidiMessage[0]))
644642
{
645-
midiMessage |= (inProgressMidiMessage[1] << 8);
646-
}
643+
// Convert from the QPC time to the number of ticks elapsed from the start time.
644+
DWORD ticks = (DWORD)(((position - startTime) / m_qpcFrequency) * 1000.0);
645+
DWORD_PTR midiMessage{ static_cast<DWORD_PTR>(inProgressMidiMessage[0]) };
647646

648-
if (MIDI_MESSAGE_IS_THREE_BYTES(inProgressMidiMessage[0]))
649-
{
650-
midiMessage |= (inProgressMidiMessage[2] << 16);
651-
}
647+
if (MIDI_MESSAGE_IS_TWO_BYTES(inProgressMidiMessage[0]) || MIDI_MESSAGE_IS_THREE_BYTES(inProgressMidiMessage[0]))
648+
{
649+
midiMessage |= (static_cast<DWORD_PTR>(inProgressMidiMessage[1]) << 8);
650+
}
652651

653-
WinmmClientCallback(MIM_DATA, midiMessage, ticks);
652+
if (MIDI_MESSAGE_IS_THREE_BYTES(inProgressMidiMessage[0]))
653+
{
654+
midiMessage |= (static_cast<DWORD_PTR>(inProgressMidiMessage[2]) << 16);
655+
}
656+
657+
WinmmClientCallback(MIM_DATA, midiMessage, ticks);
658+
659+
// reset for next message
660+
countMidiMessageBytesReceived = 0;
654661

655-
// reset for next message
656-
countMidiMessageBytesReceived = 0;
657-
inProgressMidiMessage[0] = 0;
662+
inProgressMidiMessage[0] = 0;
663+
inProgressMidiMessage[1] = 0;
664+
inProgressMidiMessage[2] = 0;
665+
}
658666
}
659667

660668
// move to the next byte of data in the loop
@@ -712,9 +720,30 @@ CMidiPort::SendMidiMessage(UINT32 midiMessage)
712720
// This should be on an initialized midi out port
713721
RETURN_HR_IF(E_INVALIDARG, nullptr == m_MidisrvTransport);
714722

723+
// NOTE: sizeof(midiMessage) there is not correct for how the service reads data. This results
724+
// in extra 00 byte data being sent to the service, and then in the translator, being read as
725+
// running status values for the initial status byte.
726+
727+
UINT messageSize{ sizeof(UINT32) };
728+
byte status = midiMessage & 0x000000FF;
729+
//byte* messagePointer = (byte*)(&midiMessage);
730+
731+
if (MIDI_MESSAGE_IS_ONE_BYTE(status))
732+
{
733+
messageSize = 1;
734+
}
735+
else if (MIDI_MESSAGE_IS_TWO_BYTES(status))
736+
{
737+
messageSize = 2;
738+
}
739+
else if (MIDI_MESSAGE_IS_THREE_BYTES(status))
740+
{
741+
messageSize = 3;
742+
}
743+
715744
// send the message to the transport
716745
// pass a timestamp of 0 to bypass scheduler
717-
RETURN_IF_FAILED(m_MidisrvTransport->SendMidiMessage(&midiMessage, sizeof(midiMessage), 0));
746+
RETURN_IF_FAILED(m_MidisrvTransport->SendMidiMessage(&midiMessage, messageSize, 0));
718747
}
719748

720749
return S_OK;
@@ -759,7 +788,8 @@ CMidiPort::SendLongMessage(LPMIDIHDR buffer)
759788
// pass a timestamp of 0 to bypass scheduler
760789
// TODO: based on the buffer length, this message may require chunking into smaller
761790
// pieces to ensure it fits into the cross process queue.
762-
RETURN_IF_FAILED(m_MidisrvTransport->SendMidiMessage(buffer->lpData, buffer->dwBufferLength, 0));
791+
//
792+
RETURN_IF_FAILED(m_MidisrvTransport->SendMidiMessage(buffer->lpData, buffer->dwBytesRecorded, 0));
763793
}
764794

765795
// mark the buffer as completed

0 commit comments

Comments
 (0)