1 /*
2 Copyright (C) 2010 Devin Anderson
3 
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.
8 
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.
13 
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.
17 
18 */
19 
20 #include <memory>
21 
22 #include "JackFFADOMidiOutputPort.h"
23 #include "JackMidiUtil.h"
24 #include "JackError.h"
25 
26 using Jack::JackFFADOMidiOutputPort;
27 
JackFFADOMidiOutputPort(size_t non_rt_size,size_t max_non_rt_messages,size_t max_rt_messages)28 JackFFADOMidiOutputPort::JackFFADOMidiOutputPort(size_t non_rt_size,
29                                                  size_t max_non_rt_messages,
30                                                  size_t max_rt_messages)
31 {
32     event = 0;
33     read_queue = new JackMidiBufferReadQueue();
34     std::unique_ptr<JackMidiBufferReadQueue> read_queue_ptr(read_queue);
35     send_queue = new JackFFADOMidiSendQueue();
36     std::unique_ptr<JackFFADOMidiSendQueue> send_queue_ptr(send_queue);
37     raw_queue = new JackMidiRawOutputWriteQueue(send_queue, non_rt_size,
38                                                 max_non_rt_messages,
39                                                 max_rt_messages);
40     send_queue_ptr.release();
41     read_queue_ptr.release();
42 }
43 
~JackFFADOMidiOutputPort()44 JackFFADOMidiOutputPort::~JackFFADOMidiOutputPort()
45 {
46     delete raw_queue;
47     delete read_queue;
48     delete send_queue;
49 }
50 
51 void
Process(JackMidiBuffer * port_buffer,uint32_t * output_buffer,jack_nframes_t frames)52 JackFFADOMidiOutputPort::Process(JackMidiBuffer *port_buffer,
53                                  uint32_t *output_buffer,
54                                  jack_nframes_t frames)
55 {
56     read_queue->ResetMidiBuffer(port_buffer);
57     send_queue->ResetOutputBuffer(output_buffer, frames);
58     jack_nframes_t boundary_frame = GetLastFrame() + frames;
59     if (! event) {
60         event = read_queue->DequeueEvent();
61     }
62     for (; event; event = read_queue->DequeueEvent()) {
63         switch (raw_queue->EnqueueEvent(event)) {
64         case JackMidiWriteQueue::BUFFER_FULL:
65 
66             // Processing events early might free up some space in the raw
67             // output queue.
68 
69             raw_queue->Process(boundary_frame);
70             switch (raw_queue->EnqueueEvent(event)) {
71             case JackMidiWriteQueue::BUFFER_TOO_SMALL:
72                 // This shouldn't really happen.  It indicates a bug if it
73                 // does.
74                 jack_error("JackFFADOMidiOutputPort::Process - **BUG** "
75                            "JackMidiRawOutputWriteQueue::EnqueueEvent "
76                            "returned `BUFFER_FULL`, and then returned "
77                            "`BUFFER_TOO_SMALL` after a `Process()` call.");
78                 // Fallthrough on purpose
79             case JackMidiWriteQueue::OK:
80                 continue;
81             default:
82                 return;
83             }
84         case JackMidiWriteQueue::BUFFER_TOO_SMALL:
85             jack_error("JackFFADOMidiOutputPort::Process - The write queue "
86                        "couldn't enqueue a %d-byte event. Dropping event.",
87                        event->size);
88             // Fallthrough on purpose
89         case JackMidiWriteQueue::OK:
90             continue;
91         default:
92             // This is here to stop compilers from warning us about not
93             // handling enumeration values.
94             ;
95         }
96         break;
97     }
98     raw_queue->Process(boundary_frame);
99 }
100