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 "JackALSARawMidiInputPort.h"
00024 #include "JackMidiUtil.h"
00025 #include "JackError.h"
00026
00027 using Jack::JackALSARawMidiInputPort;
00028
00029 JackALSARawMidiInputPort::JackALSARawMidiInputPort(snd_rawmidi_info_t *info,
00030 size_t index,
00031 size_t max_bytes,
00032 size_t max_messages):
00033 JackALSARawMidiPort(info, index, POLLIN)
00034 {
00035 alsa_event = 0;
00036 jack_event = 0;
00037 receive_queue = new JackALSARawMidiReceiveQueue(rawmidi, max_bytes);
00038 std::auto_ptr<JackALSARawMidiReceiveQueue> receive_ptr(receive_queue);
00039 thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
00040 std::auto_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
00041 write_queue = new JackMidiBufferWriteQueue();
00042 std::auto_ptr<JackMidiBufferWriteQueue> write_ptr(write_queue);
00043 raw_queue = new JackMidiRawInputWriteQueue(thread_queue, max_bytes,
00044 max_messages);
00045 write_ptr.release();
00046 thread_ptr.release();
00047 receive_ptr.release();
00048 }
00049
00050 JackALSARawMidiInputPort::~JackALSARawMidiInputPort()
00051 {
00052 delete raw_queue;
00053 delete receive_queue;
00054 delete thread_queue;
00055 delete write_queue;
00056 }
00057
00058 bool
00059 JackALSARawMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
00060 jack_nframes_t frames)
00061 {
00062 write_queue->ResetMidiBuffer(port_buffer, frames);
00063 bool dequeued = false;
00064 if (! jack_event) {
00065 goto dequeue_event;
00066 }
00067 for (;;) {
00068 switch (write_queue->EnqueueEvent(jack_event, frames)) {
00069 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
00070 jack_error("JackALSARawMidiInputPort::ProcessJack - The write "
00071 "queue couldn't enqueue a %d-byte event. Dropping "
00072 "event.", jack_event->size);
00073
00074 case JackMidiWriteQueue::OK:
00075 break;
00076 default:
00077 goto trigger_queue_event;
00078 }
00079 dequeue_event:
00080 jack_event = thread_queue->DequeueEvent();
00081 if (! jack_event) {
00082 break;
00083 }
00084 dequeued = true;
00085 }
00086 trigger_queue_event:
00087 return dequeued ? TriggerQueueEvent() : true;
00088 }
00089
00090 bool
00091 JackALSARawMidiInputPort::ProcessPollEvents(jack_nframes_t current_frame)
00092 {
00093 if (GetQueuePollEvent() == -1) {
00094 return false;
00095 }
00096 int io_event = GetIOPollEvent();
00097 switch (io_event) {
00098 case -1:
00099 return false;
00100 case 1:
00101 alsa_event = receive_queue->DequeueEvent();
00102 }
00103 if (alsa_event) {
00104 size_t size = alsa_event->size;
00105 size_t space = raw_queue->GetAvailableSpace();
00106 bool enough_room = space >= size;
00107 if (enough_room) {
00108 assert(raw_queue->EnqueueEvent(current_frame, size,
00109 alsa_event->buffer) ==
00110 JackMidiWriteQueue::OK);
00111 alsa_event = 0;
00112 } else if (space) {
00113 assert(raw_queue->EnqueueEvent(current_frame, space,
00114 alsa_event->buffer) ==
00115 JackMidiWriteQueue::OK);
00116 alsa_event->buffer += space;
00117 alsa_event->size -= space;
00118 }
00119 SetIOEventsEnabled(enough_room);
00120 }
00121 raw_queue->Process();
00122 return true;
00123 }