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