Launchpad.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include "Launchpad.h"
  2. #include <string>
  3. namespace midi {
  4. Launchpad::Launchpad()
  5. : midiin(), midiout(), keyPressedCallback(0), keyReleasedCallback(0)
  6. {
  7. // define callback before opening port to keep the message queue empty.
  8. midiin.setCallback(midiMessageCallback, (void*) this);
  9. for(unsigned int i=0; i<midiout.getPortCount(); i++)
  10. {
  11. if(midiout.getPortName(i).find("Launchpad") != std::string::npos)
  12. {
  13. midiout.openPort(i);
  14. break;
  15. }
  16. }
  17. if(!midiout.isPortOpen())
  18. {
  19. throw "no launchpad for midi output found";
  20. }
  21. for(unsigned int i=0; i<midiin.getPortCount(); i++)
  22. {
  23. if(midiin.getPortName(i).find("Launchpad") != std::string::npos)
  24. {
  25. midiin.openPort(i);
  26. break;
  27. }
  28. }
  29. if(!midiin.isPortOpen())
  30. {
  31. throw "no launchpad for midi input found";
  32. }
  33. }
  34. void Launchpad::midiMessageCallback(double timeStamp, Message &message, void *userData)
  35. {
  36. Launchpad *launchpad = (Launchpad*) userData;
  37. // use runtime type information to check for the message type.
  38. // this requires the specified class to have a virtual member.
  39. NoteMessage *noteMessage = dynamic_cast<NoteMessage*>(&message);
  40. if(noteMessage)
  41. {
  42. unsigned char x = noteMessage->pitch % 16;
  43. unsigned char y = 7 - noteMessage->pitch / 16;
  44. if(dynamic_cast<NoteOnMessage*>(noteMessage))
  45. {
  46. launchpad->keyPressed(x, y);
  47. }
  48. else
  49. {
  50. launchpad->keyReleased(x, y);
  51. }
  52. }
  53. else
  54. {
  55. ControlChangeMessage *controlChangeMessage = dynamic_cast<ControlChangeMessage*>(&message);
  56. if(controlChangeMessage)
  57. {
  58. unsigned char x = controlChangeMessage->control - 104;
  59. unsigned char y = 8;
  60. if(controlChangeMessage->value == 127)
  61. {
  62. launchpad->keyPressed(x, y);
  63. }
  64. else
  65. {
  66. launchpad->keyReleased(x, y);
  67. }
  68. }
  69. }
  70. }
  71. bool Launchpad::issetColor(unsigned char x, unsigned char y) const
  72. {
  73. return colorSet[x][y];
  74. }
  75. const LaunchpadColor& Launchpad::getColor(unsigned char x, unsigned char y) const
  76. {
  77. return colors[x][y];
  78. }
  79. void Launchpad::setColor(unsigned char x, unsigned char y, const LaunchpadColor& color)
  80. {
  81. if(x >= width || y >= height || (x == 8 && y == 8))
  82. {
  83. throw "specified launchpad position is out of range";
  84. }
  85. if(color.red > 3 || color.green > 3)
  86. {
  87. throw "specified launchpad color is out of range";
  88. }
  89. unsigned char velocity = (color.green << 4) + color.red;
  90. if(y == 8)
  91. {
  92. midiout.sendMessage(ControlChangeMessage(
  93. 0,
  94. 104 + x,
  95. velocity
  96. ));
  97. }
  98. else
  99. {
  100. midiout.sendMessage(NoteOnMessage(
  101. 0,
  102. ((7 - y) << 4) + x,
  103. velocity
  104. ));
  105. }
  106. colors[x][y] = color;
  107. colorSet[x][y] = true;
  108. }
  109. void Launchpad::setColorAll(const LaunchpadColor& color)
  110. {
  111. for(unsigned char x = 0; x < width; x++)
  112. {
  113. for(unsigned char y = 0; y < height; y++)
  114. {
  115. if(x != 8 || y != 8)
  116. {
  117. setColor(x, y, color);
  118. }
  119. }
  120. }
  121. }
  122. void Launchpad::keyPressed(unsigned char x, unsigned char y)
  123. {
  124. if(keyPressedCallback)
  125. {
  126. keyPressedCallback(x, y, keyEventCallbackData);
  127. }
  128. }
  129. void Launchpad::keyReleased(unsigned char x, unsigned char y)
  130. {
  131. if(keyReleasedCallback)
  132. {
  133. keyReleasedCallback(x, y, keyEventCallbackData);
  134. }
  135. }
  136. } // namespace