jack2 codebase
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.

125 lines
4.0KB

  1. #include <memory>
  2. #include "JackALSARawMidiInputPort.h"
  3. #include "JackMidiUtil.h"
  4. using Jack::JackALSARawMidiInputPort;
  5. JackALSARawMidiInputPort::JackALSARawMidiInputPort(snd_rawmidi_info_t *info,
  6. size_t index,
  7. size_t max_bytes,
  8. size_t max_messages):
  9. JackALSARawMidiPort(info, index)
  10. {
  11. alsa_event = 0;
  12. jack_event = 0;
  13. receive_queue = new JackALSARawMidiReceiveQueue(rawmidi, max_bytes);
  14. std::auto_ptr<JackALSARawMidiReceiveQueue> receive_ptr(receive_queue);
  15. thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
  16. std::auto_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
  17. write_queue = new JackMidiBufferWriteQueue();
  18. std::auto_ptr<JackMidiBufferWriteQueue> write_ptr(write_queue);
  19. raw_queue = new JackMidiRawInputWriteQueue(thread_queue, max_bytes,
  20. max_messages);
  21. write_ptr.release();
  22. thread_ptr.release();
  23. receive_ptr.release();
  24. }
  25. JackALSARawMidiInputPort::~JackALSARawMidiInputPort()
  26. {
  27. delete raw_queue;
  28. delete receive_queue;
  29. delete thread_queue;
  30. delete write_queue;
  31. }
  32. jack_nframes_t
  33. JackALSARawMidiInputPort::EnqueueALSAEvent()
  34. {
  35. switch (raw_queue->EnqueueEvent(alsa_event)) {
  36. case JackMidiWriteQueue::BUFFER_FULL:
  37. // Processing events early might free up some space in the raw queue.
  38. raw_queue->Process();
  39. switch (raw_queue->EnqueueEvent(alsa_event)) {
  40. case JackMidiWriteQueue::BUFFER_TOO_SMALL:
  41. jack_error("JackALSARawMidiInputPort::Process - **BUG** "
  42. "JackMidiRawInputWriteQueue::EnqueueEvent returned "
  43. "`BUFFER_FULL` and then returned `BUFFER_TOO_SMALL` "
  44. "after a `Process()` call.");
  45. // Fallthrough on purpose
  46. case JackMidiWriteQueue::OK:
  47. return 0;
  48. default:
  49. ;
  50. }
  51. break;
  52. case JackMidiWriteQueue::BUFFER_TOO_SMALL:
  53. jack_error("JackALSARawMidiInputPort::Execute - The thread queue "
  54. "couldn't enqueue a %d-byte packet. Dropping event.",
  55. alsa_event->size);
  56. // Fallthrough on purpose
  57. case JackMidiWriteQueue::OK:
  58. return 0;
  59. default:
  60. ;
  61. }
  62. jack_nframes_t alsa_time = alsa_event->time;
  63. jack_nframes_t next_time = raw_queue->Process();
  64. return (next_time < alsa_time) ? next_time : alsa_time;
  65. }
  66. bool
  67. JackALSARawMidiInputPort::ProcessALSA(jack_nframes_t *frame)
  68. {
  69. unsigned short revents;
  70. if (! ProcessPollEvents(&revents)) {
  71. return false;
  72. }
  73. if (alsa_event) {
  74. *frame = EnqueueALSAEvent();
  75. if (*frame) {
  76. return true;
  77. }
  78. }
  79. if (revents & POLLIN) {
  80. for (alsa_event = receive_queue->DequeueEvent(); alsa_event;
  81. alsa_event = receive_queue->DequeueEvent()) {
  82. *frame = EnqueueALSAEvent();
  83. if (*frame) {
  84. return true;
  85. }
  86. }
  87. }
  88. *frame = raw_queue->Process();
  89. return true;
  90. }
  91. bool
  92. JackALSARawMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
  93. jack_nframes_t frames)
  94. {
  95. write_queue->ResetMidiBuffer(port_buffer, frames);
  96. if (! jack_event) {
  97. jack_event = thread_queue->DequeueEvent();
  98. }
  99. for (; jack_event; jack_event = thread_queue->DequeueEvent()) {
  100. // We add `frames` so that MIDI events align with audio as closely as
  101. // possible.
  102. switch (write_queue->EnqueueEvent(jack_event, frames)) {
  103. case JackMidiWriteQueue::BUFFER_TOO_SMALL:
  104. jack_error("JackALSARawMidiInputPort::ProcessJack - The write "
  105. "queue couldn't enqueue a %d-byte event. Dropping "
  106. "event.", jack_event->size);
  107. // Fallthrough on purpose
  108. case JackMidiWriteQueue::OK:
  109. continue;
  110. default:
  111. ;
  112. }
  113. break;
  114. }
  115. return true;
  116. }