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