2 Copyright (C) 2011 Devin Anderson
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "JackALSARawMidiOutputPort.h"
24 #include "JackError.h"
26 using Jack::JackALSARawMidiOutputPort
;
28 JackALSARawMidiOutputPort::JackALSARawMidiOutputPort(const char* client_name
,
29 snd_rawmidi_info_t
*info
,
31 size_t max_bytes_per_poll
,
34 JackALSARawMidiPort(client_name
, info
, index
, POLLOUT
)
37 read_queue
= new JackMidiBufferReadQueue();
38 std::unique_ptr
<JackMidiBufferReadQueue
> read_ptr(read_queue
);
39 send_queue
= new JackALSARawMidiSendQueue(rawmidi
, max_bytes_per_poll
);
40 std::unique_ptr
<JackALSARawMidiSendQueue
> send_ptr(send_queue
);
41 thread_queue
= new JackMidiAsyncQueue(max_bytes
, max_messages
);
42 std::unique_ptr
<JackMidiAsyncQueue
> thread_ptr(thread_queue
);
43 raw_queue
= new JackMidiRawOutputWriteQueue(send_queue
, max_bytes
,
44 max_messages
, max_messages
);
50 JackALSARawMidiOutputPort::~JackALSARawMidiOutputPort()
59 JackALSARawMidiOutputPort::ProcessJack(JackMidiBuffer
*port_buffer
,
60 jack_nframes_t frames
)
62 read_queue
->ResetMidiBuffer(port_buffer
);
63 bool enqueued
= false;
64 for (jack_midi_event_t
*event
= read_queue
->DequeueEvent(); event
;
65 event
= read_queue
->DequeueEvent()) {
66 switch (thread_queue
->EnqueueEvent(event
, frames
)) {
67 case JackMidiWriteQueue::BUFFER_FULL
:
68 jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread "
69 "queue doesn't have enough room to enqueue a %d-byte "
70 "event. Dropping event.", event
->size
);
72 case JackMidiWriteQueue::BUFFER_TOO_SMALL
:
73 jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread "
74 "queue is too small to enqueue a %d-byte event. "
75 "Dropping event.", event
->size
);
81 return enqueued
? TriggerQueueEvent() : true;
85 JackALSARawMidiOutputPort::ProcessPollEvents(bool handle_output
, bool timeout
,
86 jack_nframes_t
*frame
)
90 send_queue
->ResetPollByteCount();
91 if (! handle_output
) {
93 goto process_raw_queue
;
95 io_event
= GetIOPollEvent();
99 queue_event
= GetQueuePollEvent();
100 if (queue_event
== -1) {
103 if (io_event
|| timeout
) {
105 // We call the 'Process' event early because there are events waiting
106 // to be processed that either need to be sent now, or before now.
107 raw_queue
->Process();
108 } else if (! queue_event
) {
112 alsa_event
= thread_queue
->DequeueEvent();
114 for (; alsa_event
; alsa_event
= thread_queue
->DequeueEvent()) {
115 switch (raw_queue
->EnqueueEvent(alsa_event
)) {
116 case JackMidiWriteQueue::BUFFER_TOO_SMALL
:
117 jack_error("JackALSARawMidiOutputPort::ProcessQueues - The raw "
118 "output queue couldn't enqueue a %d-byte event. "
119 "Dropping event.", alsa_event
->size
);
120 // Fallthrough on purpose.
121 case JackMidiWriteQueue::OK
:
127 // Try to free up some space by processing events early.
128 *frame
= raw_queue
->Process();
130 switch (raw_queue
->EnqueueEvent(alsa_event
)) {
131 case JackMidiWriteQueue::BUFFER_FULL
:
133 case JackMidiWriteQueue::BUFFER_TOO_SMALL
:
134 // This shouldn't happen.
140 *frame
= raw_queue
->Process();
142 bool blocked
= send_queue
->IsBlocked();
143 SetIOEventsEnabled(blocked
);