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.

155 lines
3.5KB

  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. master->setController(ev.channel, ev.num, ev.value);
  78. break;
  79. case M_PGMCHANGE:
  80. for(int i=0; i < NUM_MIDI_PARTS; ++i) {
  81. //set the program of the parts assigned to the midi channel
  82. if(master->part[i]->Prcvchn == ev.channel) {
  83. middleware->pendingSetProgram(i, ev.num);
  84. }
  85. }
  86. break;
  87. case M_PRESSURE:
  88. master->polyphonicAftertouch(ev.channel, ev.num, ev.value);
  89. break;
  90. }
  91. }
  92. }
  93. bool InMgr::empty(void) const
  94. {
  95. int semvalue = work.getvalue();
  96. return semvalue <= 0;
  97. }
  98. bool InMgr::setSource(string name)
  99. {
  100. MidiIn *src = getIn(name);
  101. if(!src)
  102. return false;
  103. if(current)
  104. current->setMidiEn(false);
  105. current = src;
  106. current->setMidiEn(true);
  107. bool success = current->getMidiEn();
  108. //Keep system in a valid state (aka with a running driver)
  109. if(!success)
  110. (current = getIn("NULL"))->setMidiEn(true);
  111. return success;
  112. }
  113. string InMgr::getSource() const
  114. {
  115. if(current)
  116. return current->name;
  117. else
  118. return "ERROR";
  119. }
  120. MidiIn *InMgr::getIn(string name)
  121. {
  122. EngineMgr &eng = EngineMgr::getInstance(NULL);
  123. return dynamic_cast<MidiIn *>(eng.getEng(name));
  124. }
  125. void InMgr::setMaster(Master *master_)
  126. {
  127. master = master_;
  128. }