2 Copyright (C) 2010 Devin Anderson
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "JackError.h"
24 #include "JackMidiRawOutputWriteQueue.h"
25 #include "JackMidiUtil.h"
27 using Jack::JackMidiRawOutputWriteQueue
;
29 #define STILL_TIME(c, b) ((! (b)) || ((c) < (b)))
31 JackMidiRawOutputWriteQueue::
32 JackMidiRawOutputWriteQueue(JackMidiSendQueue
*send_queue
, size_t non_rt_size
,
33 size_t max_non_rt_messages
, size_t max_rt_messages
)
35 non_rt_queue
= new JackMidiAsyncQueue(non_rt_size
, max_non_rt_messages
);
36 std::auto_ptr
<JackMidiAsyncQueue
> non_rt_ptr(non_rt_queue
);
37 rt_queue
= new JackMidiAsyncQueue(max_rt_messages
, max_rt_messages
);
38 std::auto_ptr
<JackMidiAsyncQueue
> rt_ptr(rt_queue
);
42 this->send_queue
= send_queue
;
47 JackMidiRawOutputWriteQueue::~JackMidiRawOutputWriteQueue()
54 JackMidiRawOutputWriteQueue::DequeueNonRealtimeEvent()
56 non_rt_event
= non_rt_queue
->DequeueEvent();
58 non_rt_event_time
= non_rt_event
->time
;
59 running_status
= ApplyRunningStatus(non_rt_event
, running_status
);
64 JackMidiRawOutputWriteQueue::DequeueRealtimeEvent()
66 rt_event
= rt_queue
->DequeueEvent();
68 rt_event_time
= rt_event
->time
;
72 Jack::JackMidiWriteQueue::EnqueueResult
73 JackMidiRawOutputWriteQueue::EnqueueEvent(jack_nframes_t time
, size_t size
,
74 jack_midi_data_t
*buffer
)
76 JackMidiAsyncQueue
*queue
= (size
== 1) && (*buffer
>= 0xf8) ? rt_queue
:
78 return queue
->EnqueueEvent(time
, size
, buffer
);
82 JackMidiRawOutputWriteQueue::HandleWriteQueueBug(jack_nframes_t time
,
83 jack_midi_data_t byte
)
85 jack_error("JackMidiRawOutputWriteQueue::HandleWriteQueueBug - **BUG** "
86 "The write queue told us that it couldn't enqueue a 1-byte "
87 "MIDI event scheduled for frame '%d'. This is probably a bug "
88 "in the write queue implementation.", time
);
92 JackMidiRawOutputWriteQueue::Process(jack_nframes_t boundary_frame
)
95 DequeueNonRealtimeEvent();
98 DequeueRealtimeEvent();
101 jack_nframes_t current_frame
= send_queue
->GetNextScheduleFrame();
102 if ((rt_event_time
> current_frame
) && non_rt_event
&&
103 (non_rt_event_time
< rt_event_time
)) {
104 if (! SendNonRTBytes(rt_event_time
< boundary_frame
?
105 rt_event_time
: boundary_frame
)) {
106 return non_rt_event_time
;
108 current_frame
= send_queue
->GetNextScheduleFrame();
110 if (! STILL_TIME(current_frame
, boundary_frame
)) {
111 return (! non_rt_event
) ? rt_event_time
:
112 non_rt_event_time
< rt_event_time
? non_rt_event_time
:
115 if (! SendByte(rt_event_time
, *(rt_event
->buffer
))) {
116 return rt_event_time
;
118 DequeueRealtimeEvent();
120 SendNonRTBytes(boundary_frame
);
121 return non_rt_event
? non_rt_event_time
: 0;
125 JackMidiRawOutputWriteQueue::SendByte(jack_nframes_t time
,
126 jack_midi_data_t byte
)
128 switch (send_queue
->EnqueueEvent(time
, 1, &byte
)) {
129 case BUFFER_TOO_SMALL
:
130 HandleWriteQueueBug(time
, byte
);
134 // This is here to stop compilers from warning us about not handling
135 // enumeration values.
142 JackMidiRawOutputWriteQueue::SendNonRTBytes(jack_nframes_t boundary_frame
)
144 while (non_rt_event
) {
145 for (; non_rt_event
->size
;
146 (non_rt_event
->size
)--, (non_rt_event
->buffer
)++) {
147 jack_nframes_t current_frame
= send_queue
->GetNextScheduleFrame();
148 if (! STILL_TIME(current_frame
, boundary_frame
)) {
151 if (! SendByte(non_rt_event_time
, *(non_rt_event
->buffer
))) {
155 DequeueNonRealtimeEvent();