Audio plugin host https://kx.studio/carla
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.

160 lines
3.8KB

  1. #include "InMgr.h"
  2. #include "MidiIn.h"
  3. #include "EngineMgr.h"
  4. #include "../Misc/Master.h"
  5. #include "../Misc/Part.h"
  6. #include "../Misc/MiddleWare.h"
  7. #include <rtosc/thread-link.h>
  8. #include <iostream>
  9. using namespace std;
  10. extern MiddleWare *middleware;
  11. ostream &operator<<(ostream &out, const MidiEvent &ev)
  12. {
  13. switch(ev.type) {
  14. case M_NOTE:
  15. out << "MidiNote: note(" << ev.num << ")\n"
  16. << " channel(" << ev.channel << ")\n"
  17. << " velocity(" << ev.value << ")";
  18. break;
  19. case M_CONTROLLER:
  20. out << "MidiCtl: controller(" << ev.num << ")\n"
  21. << " channel(" << ev.channel << ")\n"
  22. << " value(" << ev.value << ")";
  23. break;
  24. case M_PGMCHANGE:
  25. out << "PgmChange: program(" << ev.num << ")\n"
  26. << " channel(" << ev.channel << ")";
  27. break;
  28. }
  29. return out;
  30. }
  31. MidiEvent::MidiEvent()
  32. :channel(0), type(0), num(0), value(0), time(0)
  33. {}
  34. InMgr &InMgr::getInstance()
  35. {
  36. static InMgr instance;
  37. return instance;
  38. }
  39. InMgr::InMgr()
  40. :queue(100), master(NULL)
  41. {
  42. current = NULL;
  43. work.init(PTHREAD_PROCESS_PRIVATE, 0);
  44. }
  45. InMgr::~InMgr()
  46. {
  47. //lets stop the consumer thread
  48. }
  49. void InMgr::putEvent(MidiEvent ev)
  50. {
  51. if(queue.push(ev)) //check for error
  52. cerr << "ERROR: Midi Ringbuffer is FULL" << endl;
  53. else
  54. work.post();
  55. }
  56. void InMgr::flush(unsigned frameStart, unsigned frameStop)
  57. {
  58. MidiEvent ev;
  59. while(!work.trywait()) {
  60. queue.peak(ev);
  61. if(ev.time < (int)frameStart || ev.time > (int)frameStop) {
  62. //Back out of transaction
  63. work.post();
  64. //printf("%d vs [%d..%d]\n",ev.time, frameStart, frameStop);
  65. break;
  66. }
  67. queue.pop(ev);
  68. //cout << ev << endl;
  69. switch(ev.type) {
  70. case M_NOTE:
  71. if(ev.value)
  72. master->noteOn(ev.channel, ev.num, ev.value);
  73. else
  74. master->noteOff(ev.channel, ev.num);
  75. break;
  76. case M_CONTROLLER:
  77. if(ev.num == C_bankselectmsb) // Change current bank
  78. middleware->spawnMaster()->bToU->write("/bank/msb", "i", ev.value);
  79. else if(ev.num == C_bankselectlsb) // Change current bank (LSB)
  80. middleware->spawnMaster()->bToU->write("/bank/lsb", "i", ev.value);
  81. else
  82. master->setController(ev.channel, ev.num, ev.value);
  83. break;
  84. case M_PGMCHANGE:
  85. for(int i=0; i < NUM_MIDI_PARTS; ++i) {
  86. //set the program of the parts assigned to the midi channel
  87. if(master->part[i]->Prcvchn == ev.channel) {
  88. middleware->pendingSetProgram(i, ev.num);
  89. }
  90. }
  91. break;
  92. case M_PRESSURE:
  93. master->polyphonicAftertouch(ev.channel, ev.num, ev.value);
  94. break;
  95. }
  96. }
  97. }
  98. bool InMgr::empty(void) const
  99. {
  100. int semvalue = work.getvalue();
  101. return semvalue <= 0;
  102. }
  103. bool InMgr::setSource(string name)
  104. {
  105. MidiIn *src = getIn(name);
  106. if(!src)
  107. return false;
  108. if(current)
  109. current->setMidiEn(false);
  110. current = src;
  111. current->setMidiEn(true);
  112. bool success = current->getMidiEn();
  113. //Keep system in a valid state (aka with a running driver)
  114. if(!success)
  115. (current = getIn("NULL"))->setMidiEn(true);
  116. return success;
  117. }
  118. string InMgr::getSource() const
  119. {
  120. if(current)
  121. return current->name;
  122. else
  123. return "ERROR";
  124. }
  125. MidiIn *InMgr::getIn(string name)
  126. {
  127. EngineMgr &eng = EngineMgr::getInstance(NULL);
  128. return dynamic_cast<MidiIn *>(eng.getEng(name));
  129. }
  130. void InMgr::setMaster(Master *master_)
  131. {
  132. master = master_;
  133. }