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