Jack2 1.9.10
|
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 #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 // Fallthrough on purpose. 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 }