00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <memory>
00021 #include <new>
00022
00023 #include "JackError.h"
00024 #include "JackMidiRawOutputWriteQueue.h"
00025 #include "JackMidiUtil.h"
00026
00027 using Jack::JackMidiRawOutputWriteQueue;
00028
00029 #define STILL_TIME(c, b) ((! (b)) || ((c) < (b)))
00030
00031 JackMidiRawOutputWriteQueue::
00032 JackMidiRawOutputWriteQueue(JackMidiSendQueue *send_queue, size_t non_rt_size,
00033 size_t max_non_rt_messages, size_t max_rt_messages)
00034 {
00035 non_rt_queue = new JackMidiAsyncQueue(non_rt_size, max_non_rt_messages);
00036 std::auto_ptr<JackMidiAsyncQueue> non_rt_ptr(non_rt_queue);
00037 rt_queue = new JackMidiAsyncQueue(max_rt_messages, max_rt_messages);
00038 std::auto_ptr<JackMidiAsyncQueue> rt_ptr(rt_queue);
00039 non_rt_event = 0;
00040 rt_event = 0;
00041 running_status = 0;
00042 this->send_queue = send_queue;
00043 rt_ptr.release();
00044 non_rt_ptr.release();
00045 }
00046
00047 JackMidiRawOutputWriteQueue::~JackMidiRawOutputWriteQueue()
00048 {
00049 delete non_rt_queue;
00050 delete rt_queue;
00051 }
00052
00053 void
00054 JackMidiRawOutputWriteQueue::DequeueNonRealtimeEvent()
00055 {
00056 non_rt_event = non_rt_queue->DequeueEvent();
00057 if (non_rt_event) {
00058 non_rt_event_time = non_rt_event->time;
00059 running_status = ApplyRunningStatus(non_rt_event, running_status);
00060 }
00061 }
00062
00063 void
00064 JackMidiRawOutputWriteQueue::DequeueRealtimeEvent()
00065 {
00066 rt_event = rt_queue->DequeueEvent();
00067 if (rt_event) {
00068 rt_event_time = rt_event->time;
00069 }
00070 }
00071
00072 Jack::JackMidiWriteQueue::EnqueueResult
00073 JackMidiRawOutputWriteQueue::EnqueueEvent(jack_nframes_t time, size_t size,
00074 jack_midi_data_t *buffer)
00075 {
00076 JackMidiAsyncQueue *queue = (size == 1) && (*buffer >= 0xf8) ? rt_queue :
00077 non_rt_queue;
00078 return queue->EnqueueEvent(time, size, buffer);
00079 }
00080
00081 void
00082 JackMidiRawOutputWriteQueue::HandleWriteQueueBug(jack_nframes_t time,
00083 jack_midi_data_t byte)
00084 {
00085 jack_error("JackMidiRawOutputWriteQueue::HandleWriteQueueBug - **BUG** "
00086 "The write queue told us that it couldn't enqueue a 1-byte "
00087 "MIDI event scheduled for frame '%d'. This is probably a bug "
00088 "in the write queue implementation.", time);
00089 }
00090
00091 jack_nframes_t
00092 JackMidiRawOutputWriteQueue::Process(jack_nframes_t boundary_frame)
00093 {
00094 if (! non_rt_event) {
00095 DequeueNonRealtimeEvent();
00096 }
00097 if (! rt_event) {
00098 DequeueRealtimeEvent();
00099 }
00100 while (rt_event) {
00101 jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
00102 if ((rt_event_time > current_frame) && non_rt_event &&
00103 (non_rt_event_time < rt_event_time)) {
00104 if (! SendNonRTBytes(rt_event_time < boundary_frame ?
00105 rt_event_time : boundary_frame)) {
00106 return non_rt_event_time;
00107 }
00108 current_frame = send_queue->GetNextScheduleFrame();
00109 }
00110 if (! STILL_TIME(current_frame, boundary_frame)) {
00111 return (! non_rt_event) ? rt_event_time :
00112 non_rt_event_time < rt_event_time ? non_rt_event_time :
00113 rt_event_time;
00114 }
00115 if (! SendByte(rt_event_time, *(rt_event->buffer))) {
00116 return rt_event_time;
00117 }
00118 DequeueRealtimeEvent();
00119 }
00120 SendNonRTBytes(boundary_frame);
00121 return non_rt_event ? non_rt_event_time : 0;
00122 }
00123
00124 bool
00125 JackMidiRawOutputWriteQueue::SendByte(jack_nframes_t time,
00126 jack_midi_data_t byte)
00127 {
00128 switch (send_queue->EnqueueEvent(time, 1, &byte)) {
00129 case BUFFER_TOO_SMALL:
00130 HandleWriteQueueBug(time, byte);
00131 case OK:
00132 return true;
00133 default:
00134
00135
00136 ;
00137 }
00138 return false;
00139 }
00140
00141 bool
00142 JackMidiRawOutputWriteQueue::SendNonRTBytes(jack_nframes_t boundary_frame)
00143 {
00144 while (non_rt_event) {
00145 for (; non_rt_event->size;
00146 (non_rt_event->size)--, (non_rt_event->buffer)++) {
00147 jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
00148 if (! STILL_TIME(current_frame, boundary_frame)) {
00149 return true;
00150 }
00151 if (! SendByte(non_rt_event_time, *(non_rt_event->buffer))) {
00152 return false;
00153 }
00154 }
00155 DequeueNonRealtimeEvent();
00156 }
00157 return true;
00158 }