00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <cassert>
00021 #include <memory>
00022
00023 #include "JackALSARawMidiOutputPort.h"
00024 #include "JackError.h"
00025
00026 using Jack::JackALSARawMidiOutputPort;
00027
00028 JackALSARawMidiOutputPort::JackALSARawMidiOutputPort(snd_rawmidi_info_t *info,
00029 size_t index,
00030 size_t max_bytes_per_poll,
00031 size_t max_bytes,
00032 size_t max_messages):
00033 JackALSARawMidiPort(info, index, POLLOUT)
00034 {
00035 alsa_event = 0;
00036 read_queue = new JackMidiBufferReadQueue();
00037 std::auto_ptr<JackMidiBufferReadQueue> read_ptr(read_queue);
00038 send_queue = new JackALSARawMidiSendQueue(rawmidi, max_bytes_per_poll);
00039 std::auto_ptr<JackALSARawMidiSendQueue> send_ptr(send_queue);
00040 thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
00041 std::auto_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
00042 raw_queue = new JackMidiRawOutputWriteQueue(send_queue, max_bytes,
00043 max_messages, max_messages);
00044 thread_ptr.release();
00045 send_ptr.release();
00046 read_ptr.release();
00047 }
00048
00049 JackALSARawMidiOutputPort::~JackALSARawMidiOutputPort()
00050 {
00051 delete raw_queue;
00052 delete read_queue;
00053 delete send_queue;
00054 delete thread_queue;
00055 }
00056
00057 bool
00058 JackALSARawMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer,
00059 jack_nframes_t frames)
00060 {
00061 read_queue->ResetMidiBuffer(port_buffer);
00062 bool enqueued = false;
00063 for (jack_midi_event_t *event = read_queue->DequeueEvent(); event;
00064 event = read_queue->DequeueEvent()) {
00065 switch (thread_queue->EnqueueEvent(event, frames)) {
00066 case JackMidiWriteQueue::BUFFER_FULL:
00067 jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread "
00068 "queue doesn't have enough room to enqueue a %d-byte "
00069 "event. Dropping event.", event->size);
00070 continue;
00071 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
00072 jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread "
00073 "queue is too small to enqueue a %d-byte event. "
00074 "Dropping event.", event->size);
00075 continue;
00076 default:
00077 enqueued = true;
00078 }
00079 }
00080 return enqueued ? TriggerQueueEvent() : true;
00081 }
00082
00083 bool
00084 JackALSARawMidiOutputPort::ProcessPollEvents(bool handle_output, bool timeout,
00085 jack_nframes_t *frame)
00086 {
00087 int io_event;
00088 int queue_event;
00089 send_queue->ResetPollByteCount();
00090 if (! handle_output) {
00091 assert(timeout);
00092 goto process_raw_queue;
00093 }
00094 io_event = GetIOPollEvent();
00095 if (io_event == -1) {
00096 return false;
00097 }
00098 queue_event = GetQueuePollEvent();
00099 if (queue_event == -1) {
00100 return false;
00101 }
00102 if (io_event || timeout) {
00103 process_raw_queue:
00104
00105
00106 raw_queue->Process();
00107 } else if (! queue_event) {
00108 return true;
00109 }
00110 if (! alsa_event) {
00111 alsa_event = thread_queue->DequeueEvent();
00112 }
00113 for (; alsa_event; alsa_event = thread_queue->DequeueEvent()) {
00114 switch (raw_queue->EnqueueEvent(alsa_event)) {
00115 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
00116 jack_error("JackALSARawMidiOutputPort::ProcessQueues - The raw "
00117 "output queue couldn't enqueue a %d-byte event. "
00118 "Dropping event.", alsa_event->size);
00119
00120 case JackMidiWriteQueue::OK:
00121 continue;
00122 default:
00123 ;
00124 }
00125
00126
00127 *frame = raw_queue->Process();
00128
00129 switch (raw_queue->EnqueueEvent(alsa_event)) {
00130 case JackMidiWriteQueue::BUFFER_FULL:
00131 goto set_io_events;
00132 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
00133
00134 assert(false);
00135 default:
00136 ;
00137 }
00138 }
00139 *frame = raw_queue->Process();
00140 set_io_events:
00141 bool blocked = send_queue->IsBlocked();
00142 SetIOEventsEnabled(blocked);
00143 if (blocked) {
00144 *frame = 0;
00145 }
00146 return true;
00147 }