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.

148 lines
5.3KB

  1. /*
  2. Copyright (C) 2010 Devin Anderson
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #ifndef __JackMidiRawOutputWriteQueue__
  16. #define __JackMidiRawOutputWriteQueue__
  17. #include "JackMidiAsyncQueue.h"
  18. #include "JackMidiSendQueue.h"
  19. namespace Jack {
  20. /**
  21. * This queue enqueues valid MIDI events and modifies them for raw output
  22. * to a write queue. It has a number of advantages over straight MIDI
  23. * event copying:
  24. *
  25. * -Running status: Status bytes can be omitted when the status byte of the
  26. * current MIDI message is the same as the status byte of the last sent
  27. * MIDI message.
  28. *
  29. * -Realtime messages: Realtime messages are given priority over
  30. * non-realtime messages. Realtime bytes are interspersed with
  31. * non-realtime bytes so that realtime messages can be sent as close as
  32. * possible to the time they're scheduled for sending.
  33. *
  34. * -Time optimization: Bytes in non-realtime messages are sent out early
  35. * when possible, with the last byte of the message being sent out as close
  36. * to the specified event time as possible.
  37. *
  38. * Use this queue if the MIDI API you're interfacing with allows you to
  39. * send raw MIDI bytes.
  40. */
  41. class SERVER_EXPORT JackMidiRawOutputWriteQueue:
  42. public JackMidiWriteQueue {
  43. private:
  44. jack_nframes_t last_enqueued_message_time;
  45. jack_midi_event_t *non_rt_event;
  46. jack_nframes_t non_rt_event_time;
  47. JackMidiAsyncQueue *non_rt_queue;
  48. jack_midi_event_t *rt_event;
  49. jack_nframes_t rt_event_time;
  50. JackMidiAsyncQueue *rt_queue;
  51. jack_midi_data_t running_status;
  52. JackMidiSendQueue *send_queue;
  53. bool
  54. DequeueNonRealtimeEvent();
  55. bool
  56. DequeueRealtimeEvent();
  57. bool
  58. SendByte(jack_nframes_t time, jack_midi_data_t byte);
  59. bool
  60. WriteNonRealtimeEvents(jack_nframes_t boundary_frame);
  61. bool
  62. WriteRealtimeEvents(jack_nframes_t boundary_frame);
  63. protected:
  64. /**
  65. * Override this method to specify what happens when the write queue
  66. * says that a 1-byte event is too large for its buffer. Basically,
  67. * this should never happen.
  68. */
  69. virtual void
  70. HandleWriteQueueBug(jack_nframes_t time, jack_midi_data_t byte);
  71. public:
  72. using JackMidiWriteQueue::EnqueueEvent;
  73. /**
  74. * Called to create a new raw write queue. The `send_queue` argument
  75. * is the queue to write raw bytes to. The optional `max_rt_messages`
  76. * argument specifies the number of messages that can be enqueued in
  77. * the internal realtime queue. The optional `max_non_rt_messages`
  78. * argument specifies the number of messages that can be enqueued in
  79. * the internal non-realtime queue. The optional `non_rt_size`
  80. * argument specifies the total number of MIDI bytes that can be put in
  81. * the non-realtime queue.
  82. */
  83. JackMidiRawOutputWriteQueue(JackMidiSendQueue *send_queue,
  84. size_t non_rt_size=4096,
  85. size_t max_non_rt_messages=1024,
  86. size_t max_rt_messages=128);
  87. ~JackMidiRawOutputWriteQueue();
  88. EnqueueResult
  89. EnqueueEvent(jack_nframes_t time, size_t size,
  90. jack_midi_data_t *buffer);
  91. /**
  92. * The `Process()` method should be called each time the
  93. * `EnqueueEvent()` method returns 'OK'. The `Process()` method will
  94. * return the next frame at which an event should be sent. The return
  95. * value from `Process()` depends upon the result of writing bytes to
  96. * the write queue:
  97. *
  98. * -If the return value is '0', then all events that have been enqueued
  99. * in this queue have been sent successfully to the write queue. Don't
  100. * call `Process()` again until another event has been enqueued.
  101. *
  102. * -If the return value is an earlier frame or the current frame, it
  103. * means that the write queue returned 'BUFFER_FULL', 'ERROR', or
  104. * 'EVENT_EARLY' when this queue attempted to send the next byte, and
  105. * that the byte should have already been sent, or is scheduled to be
  106. * sent *now*. `Process()` should be called again when the write queue
  107. * can enqueue events again successfully. How to determine when this
  108. * will happen is left up to the caller.
  109. *
  110. * -If the return value is in the future, then `Process()` should be
  111. * called again at that time, or after another event is enqueued.
  112. */
  113. jack_nframes_t
  114. Process(jack_nframes_t boundary_frame=0);
  115. };
  116. }
  117. #endif