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 "JackALSARawMidiOutputPort.h" 00024 00025 using Jack::JackALSARawMidiOutputPort; 00026 00027 JackALSARawMidiOutputPort::JackALSARawMidiOutputPort(snd_rawmidi_info_t *info, 00028 size_t index, 00029 size_t max_bytes_per_poll, 00030 size_t max_bytes, 00031 size_t max_messages): 00032 JackALSARawMidiPort(info, index, POLLOUT) 00033 { 00034 alsa_event = 0; 00035 read_queue = new JackMidiBufferReadQueue(); 00036 std::auto_ptr<JackMidiBufferReadQueue> read_ptr(read_queue); 00037 send_queue = new JackALSARawMidiSendQueue(rawmidi, max_bytes_per_poll); 00038 std::auto_ptr<JackALSARawMidiSendQueue> send_ptr(send_queue); 00039 thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages); 00040 std::auto_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue); 00041 raw_queue = new JackMidiRawOutputWriteQueue(send_queue, max_bytes, 00042 max_messages, max_messages); 00043 thread_ptr.release(); 00044 send_ptr.release(); 00045 read_ptr.release(); 00046 } 00047 00048 JackALSARawMidiOutputPort::~JackALSARawMidiOutputPort() 00049 { 00050 delete raw_queue; 00051 delete read_queue; 00052 delete send_queue; 00053 delete thread_queue; 00054 } 00055 00056 bool 00057 JackALSARawMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer, 00058 jack_nframes_t frames) 00059 { 00060 read_queue->ResetMidiBuffer(port_buffer); 00061 bool enqueued = false; 00062 for (jack_midi_event_t *event = read_queue->DequeueEvent(); event; 00063 event = read_queue->DequeueEvent()) { 00064 switch (thread_queue->EnqueueEvent(event, frames)) { 00065 case JackMidiWriteQueue::BUFFER_FULL: 00066 jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread " 00067 "queue doesn't have enough room to enqueue a %d-byte " 00068 "event. Dropping event.", event->size); 00069 continue; 00070 case JackMidiWriteQueue::BUFFER_TOO_SMALL: 00071 jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread " 00072 "queue is too small to enqueue a %d-byte event. " 00073 "Dropping event.", event->size); 00074 continue; 00075 default: 00076 enqueued = true; 00077 } 00078 } 00079 return enqueued ? TriggerQueueEvent() : true; 00080 } 00081 00082 bool 00083 JackALSARawMidiOutputPort::ProcessPollEvents(bool handle_output, bool timeout, 00084 jack_nframes_t *frame) 00085 { 00086 int io_event; 00087 int queue_event; 00088 send_queue->ResetPollByteCount(); 00089 if (! handle_output) { 00090 assert(timeout); 00091 goto process_raw_queue; 00092 } 00093 io_event = GetIOPollEvent(); 00094 if (io_event == -1) { 00095 return false; 00096 } 00097 queue_event = GetQueuePollEvent(); 00098 if (queue_event == -1) { 00099 return false; 00100 } 00101 if (io_event || timeout) { 00102 process_raw_queue: 00103 // We call the 'Process' event early because there are events waiting 00104 // to be processed that either need to be sent now, or before now. 00105 raw_queue->Process(); 00106 } else if (! queue_event) { 00107 return true; 00108 } 00109 if (! alsa_event) { 00110 alsa_event = thread_queue->DequeueEvent(); 00111 } 00112 for (; alsa_event; alsa_event = thread_queue->DequeueEvent()) { 00113 switch (raw_queue->EnqueueEvent(alsa_event)) { 00114 case JackMidiWriteQueue::BUFFER_TOO_SMALL: 00115 jack_error("JackALSARawMidiOutputPort::ProcessQueues - The raw " 00116 "output queue couldn't enqueue a %d-byte event. " 00117 "Dropping event.", alsa_event->size); 00118 // Fallthrough on purpose. 00119 case JackMidiWriteQueue::OK: 00120 continue; 00121 default: 00122 ; 00123 } 00124 00125 // Try to free up some space by processing events early. 00126 *frame = raw_queue->Process(); 00127 00128 switch (raw_queue->EnqueueEvent(alsa_event)) { 00129 case JackMidiWriteQueue::BUFFER_FULL: 00130 goto set_io_events; 00131 case JackMidiWriteQueue::BUFFER_TOO_SMALL: 00132 // This shouldn't happen. 00133 assert(false); 00134 default: 00135 ; 00136 } 00137 } 00138 *frame = raw_queue->Process(); 00139 set_io_events: 00140 bool blocked = send_queue->IsBlocked(); 00141 SetIOEventsEnabled(blocked); 00142 if (blocked) { 00143 *frame = 0; 00144 } 00145 return true; 00146 }