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.

144 lines
3.3KB

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