The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
4.5KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #ifndef __JUCE_MIDIDATACONCATENATOR_JUCEHEADER__
  19. #define __JUCE_MIDIDATACONCATENATOR_JUCEHEADER__
  20. //==============================================================================
  21. /**
  22. Helper class that takes chunks of incoming midi bytes, packages them into
  23. messages, and dispatches them to a midi callback.
  24. */
  25. class MidiDataConcatenator
  26. {
  27. public:
  28. //==============================================================================
  29. MidiDataConcatenator (const int initialBufferSize)
  30. : pendingData ((size_t) initialBufferSize),
  31. pendingBytes (0), pendingDataTime (0)
  32. {
  33. }
  34. void reset()
  35. {
  36. pendingBytes = 0;
  37. pendingDataTime = 0;
  38. }
  39. void pushMidiData (const void* data, int numBytes, double time,
  40. MidiInput* input, MidiInputCallback& callback)
  41. {
  42. const uint8* d = static_cast <const uint8*> (data);
  43. while (numBytes > 0)
  44. {
  45. if (pendingBytes > 0 || d[0] == 0xf0)
  46. {
  47. processSysex (d, numBytes, time, input, callback);
  48. }
  49. else
  50. {
  51. int used = 0;
  52. const MidiMessage m (d, numBytes, used, 0, time);
  53. if (used <= 0)
  54. break; // malformed message..
  55. callback.handleIncomingMidiMessage (input, m);
  56. numBytes -= used;
  57. d += used;
  58. }
  59. }
  60. }
  61. private:
  62. void processSysex (const uint8*& d, int& numBytes, double time,
  63. MidiInput* input, MidiInputCallback& callback)
  64. {
  65. if (*d == 0xf0)
  66. {
  67. pendingBytes = 0;
  68. pendingDataTime = time;
  69. }
  70. pendingData.ensureSize ((size_t) (pendingBytes + numBytes), false);
  71. uint8* totalMessage = static_cast<uint8*> (pendingData.getData());
  72. uint8* dest = totalMessage + pendingBytes;
  73. do
  74. {
  75. if (pendingBytes > 0 && *d >= 0x80)
  76. {
  77. if (*d >= 0xfa || *d == 0xf8)
  78. {
  79. callback.handleIncomingMidiMessage (input, MidiMessage (*d, time));
  80. ++d;
  81. --numBytes;
  82. }
  83. else
  84. {
  85. if (*d == 0xf7)
  86. {
  87. *dest++ = *d++;
  88. pendingBytes++;
  89. --numBytes;
  90. }
  91. break;
  92. }
  93. }
  94. else
  95. {
  96. *dest++ = *d++;
  97. pendingBytes++;
  98. --numBytes;
  99. }
  100. }
  101. while (numBytes > 0);
  102. if (pendingBytes > 0)
  103. {
  104. if (totalMessage [pendingBytes - 1] == 0xf7)
  105. {
  106. callback.handleIncomingMidiMessage (input, MidiMessage (totalMessage, pendingBytes, pendingDataTime));
  107. pendingBytes = 0;
  108. }
  109. else
  110. {
  111. callback.handlePartialSysexMessage (input, totalMessage, pendingBytes, pendingDataTime);
  112. }
  113. }
  114. }
  115. MemoryBlock pendingData;
  116. int pendingBytes;
  117. double pendingDataTime;
  118. JUCE_DECLARE_NON_COPYABLE (MidiDataConcatenator);
  119. };
  120. #endif // __JUCE_MIDIDATACONCATENATOR_JUCEHEADER__