Jack2
1.9.8
|
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 }