Jack2 1.9.8

JackALSARawMidiInputPort.cpp

00001 /*
00002 Copyright (C) 2011 Devin Anderson
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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             // Fallthrough on purpose.
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 }