introduce new all-in-RAM MIDI datastructure and use it for MIDI playback
[ardour.git] / libs / ardour / async_midi_port.cc
1 /*
2  * Copyright (C) 1998-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2013-2014 John Emmas <john@creativepost.co.uk>
4  * Copyright (C) 2014-2016 David Robillard <d@drobilla.net>
5  * Copyright (C) 2015-2016 Robin Gareus <robin@gareus.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <iostream>
23 #include <vector>
24
25 #include <glibmm/timer.h>
26
27 #include "pbd/error.h"
28 #include "pbd/stacktrace.h"
29
30 #include "midi++/types.h"
31
32 #include "ardour/async_midi_port.h"
33 #include "ardour/audioengine.h"
34 #include "ardour/midi_buffer.h"
35
36 using namespace MIDI;
37 using namespace ARDOUR;
38 using namespace std;
39 using namespace PBD;
40
41 pthread_t AsyncMIDIPort::_process_thread;
42
43 #define port_engine AudioEngine::instance()->port_engine()
44
45 AsyncMIDIPort::AsyncMIDIPort (string const & name, PortFlags flags)
46         : MidiPort (name, flags)
47         , MIDI::Port (name, MIDI::Port::Flags (0))
48         , _currently_in_cycle (false)
49         , _last_write_timestamp (0)
50         , _flush_at_cycle_start (false)
51         , have_timer (false)
52         , output_fifo (2048)
53         , input_fifo (1024)
54         , _xthread (true)
55 {
56 }
57
58 AsyncMIDIPort::~AsyncMIDIPort ()
59 {
60 }
61
62 void
63 AsyncMIDIPort::set_timer (boost::function<MIDI::samplecnt_t (void)>& f)
64 {
65         timer = f;
66         have_timer = true;
67 }
68
69 void
70 AsyncMIDIPort::flush_output_fifo (MIDI::pframes_t nframes)
71 {
72         RingBuffer< Evoral::Event<double> >::rw_vector vec = { { 0, 0 }, { 0, 0 } };
73         size_t written = 0;
74
75         output_fifo.get_read_vector (&vec);
76
77         MidiBuffer& mb (get_midi_buffer (nframes));
78
79         if (vec.len[0]) {
80                 Evoral::Event<double>* evp = vec.buf[0];
81
82                 assert (evp->size());
83                 assert (evp->buffer());
84
85                 for (size_t n = 0; n < vec.len[0]; ++n, ++evp) {
86                         if (mb.push_back (evp->time(), evp->size(), evp->buffer())) {
87                                 written++;
88                         }
89                 }
90         }
91
92         if (vec.len[1]) {
93                 Evoral::Event<double>* evp = vec.buf[1];
94
95                 assert (evp->size());
96                 assert (evp->buffer());
97
98                 for (size_t n = 0; n < vec.len[1]; ++n, ++evp) {
99                         if (mb.push_back (evp->time(), evp->size(), evp->buffer())) {
100                                 written++;
101                         }
102                 }
103         }
104
105         /* do this "atomically" after we're done pushing events into the
106          * MidiBuffer
107          */
108
109         output_fifo.increment_read_idx (written);
110 }
111
112 void
113 AsyncMIDIPort::cycle_start (MIDI::pframes_t nframes)
114 {
115         _currently_in_cycle = true;
116         MidiPort::cycle_start (nframes);
117
118         /* dump anything waiting in the output FIFO at the start of the port
119          * buffer
120          */
121
122         if (ARDOUR::Port::sends_output()) {
123                 flush_output_fifo (nframes);
124                 if (_flush_at_cycle_start) {
125                         flush_buffers (nframes);
126                 }
127         }
128
129         /* copy incoming data from the port buffer into the input FIFO
130            and if necessary wakeup the reader
131         */
132
133         if (ARDOUR::Port::receives_input()) {
134                 MidiBuffer& mb (get_midi_buffer (nframes));
135                 samplecnt_t when;
136
137                 if (have_timer) {
138                         when = timer ();
139                 } else {
140                         when = AudioEngine::instance()->sample_time_at_cycle_start();
141                 }
142
143                 for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) {
144                         if (!have_timer) {
145                                 when += (*b).time();
146                         }
147                         input_fifo.write (when, Evoral::NO_EVENT, (*b).size(), (*b).buffer());
148                 }
149
150                 if (!mb.empty()) {
151                         _xthread.wakeup ();
152                 }
153
154         }
155 }
156
157 void
158 AsyncMIDIPort::cycle_end (MIDI::pframes_t nframes)
159 {
160         if (ARDOUR::Port::sends_output() && !_flush_at_cycle_start) {
161                 /* move any additional data from output FIFO into the port
162                    buffer.
163                 */
164                 flush_output_fifo (nframes);
165         }
166
167         MidiPort::cycle_end (nframes);
168
169         _currently_in_cycle = false;
170 }
171
172 /** wait for the output FIFO to be emptied by successive process() callbacks.
173  *
174  * Cannot be called from a processing thread.
175  */
176 void
177 AsyncMIDIPort::drain (int check_interval_usecs, int total_usecs_to_wait)
178 {
179         RingBuffer< Evoral::Event<double> >::rw_vector vec = { { 0, 0 }, { 0, 0} };
180
181         if (!AudioEngine::instance()->running() || AudioEngine::instance()->session() == 0) {
182                 /* no more process calls - it will never drain */
183                 return;
184         }
185
186
187         if (is_process_thread()) {
188                 error << "Process thread called MIDI::AsyncMIDIPort::drain() - this cannot work" << endmsg;
189                 return;
190         }
191
192         microseconds_t now = get_microseconds ();
193         microseconds_t end = now + total_usecs_to_wait;
194
195         while (now < end) {
196                 output_fifo.get_write_vector (&vec);
197                 if (vec.len[0] + vec.len[1] >= output_fifo.bufsize() - 1) {
198                         break;
199                 }
200                 Glib::usleep (check_interval_usecs);
201                 now = get_microseconds();
202         }
203 }
204
205 int
206 AsyncMIDIPort::write (const MIDI::byte * msg, size_t msglen, MIDI::timestamp_t timestamp)
207 {
208         int ret = 0;
209
210         if (!ARDOUR::Port::sends_output()) {
211                 return ret;
212         }
213
214         if (!is_process_thread()) {
215
216                 /* this is the best estimate of "when" this MIDI data is being
217                  * delivered
218                  */
219
220                 _parser->set_timestamp (AudioEngine::instance()->sample_time() + timestamp);
221                 for (size_t n = 0; n < msglen; ++n) {
222                         _parser->scanner (msg[n]);
223                 }
224
225                 Glib::Threads::Mutex::Lock lm (output_fifo_lock);
226                 RingBuffer< Evoral::Event<double> >::rw_vector vec = { { 0, 0 }, { 0, 0} };
227
228                 output_fifo.get_write_vector (&vec);
229
230                 if (vec.len[0] + vec.len[1] < 1) {
231                         error << "no space in FIFO for non-process thread MIDI write" << endmsg;
232                         return 0;
233                 }
234
235                 if (vec.len[0]) {
236                         /* force each event inside the ringbuffer to own its
237                            own buffer, but let that be null and of zero size
238                            initially. When ::set() is called, the buffer will
239                            be allocated to hold a *copy* of the data we're
240                            storing, and then that buffer will be used over and
241                            over, occasionally being upwardly resized as
242                            necessary.
243                         */
244                         if (!vec.buf[0]->owns_buffer()) {
245                                 vec.buf[0]->set_buffer (0, 0, true);
246                         }
247                         vec.buf[0]->set (msg, msglen, timestamp);
248                 } else {
249                         /* see comment in previous branch of if() statement */
250                         if (!vec.buf[1]->owns_buffer()) {
251                                 vec.buf[1]->set_buffer (0, 0, true);
252                         }
253                         vec.buf[1]->set (msg, msglen, timestamp);
254                 }
255
256                 output_fifo.increment_write_idx (1);
257
258                 ret = msglen;
259
260         } else {
261
262                 _parser->set_timestamp (AudioEngine::instance()->sample_time_at_cycle_start() + timestamp);
263                 for (size_t n = 0; n < msglen; ++n) {
264                         _parser->scanner (msg[n]);
265                 }
266
267                 if (timestamp >= _cycle_nframes) {
268                         std::cerr << "attempting to write MIDI event of " << msglen << " MIDI::bytes at time "
269                                   << timestamp << " of " << _cycle_nframes
270                                   << " (this will not work - needs a code fix)"
271                                   << std::endl;
272                 }
273
274                 /* This is the process thread, which makes checking
275                  * _currently_in_cycle atomic and safe, since it is only
276                  * set from cycle_start() and cycle_end(), also called
277                  * only from the process thread.
278                  */
279
280                 if (_currently_in_cycle) {
281
282                         MidiBuffer& mb (get_midi_buffer (_cycle_nframes));
283
284                         if (timestamp == 0) {
285                                 timestamp = _last_write_timestamp;
286                         }
287
288                         if (mb.push_back (timestamp, msglen, msg)) {
289                                 ret = msglen;
290                                 _last_write_timestamp = timestamp;
291
292                         } else {
293                                 cerr << "AsyncMIDIPort (" << ARDOUR::Port::name() << "): write of " << msglen << " @ " << timestamp << " failed\n" << endl;
294                                 PBD::stacktrace (cerr, 20);
295                                 ret = 0;
296                         }
297                 } else {
298                         cerr << "write to JACK midi port failed: not currently in a process cycle." << endl;
299                         PBD::stacktrace (cerr, 20);
300                 }
301         }
302
303         return ret;
304 }
305
306
307 int
308 AsyncMIDIPort::read (MIDI::byte *, size_t)
309 {
310         if (!ARDOUR::Port::receives_input()) {
311                 return 0;
312         }
313
314         timestamp_t time;
315         Evoral::EventType type;
316         uint32_t size;
317         vector<MIDI::byte> buffer(input_fifo.capacity());
318
319         while (input_fifo.read (&time, &type, &size, &buffer[0])) {
320                 _parser->set_timestamp (time);
321                 for (uint32_t i = 0; i < size; ++i) {
322                         _parser->scanner (buffer[i]);
323                 }
324         }
325
326         return 0;
327 }
328
329 void
330 AsyncMIDIPort::parse (MIDI::samplecnt_t)
331 {
332         MIDI::byte buf[1];
333
334         /* see ::read() to realize why buf is not used */
335         read (buf, sizeof (buf));
336 }
337
338 void
339 AsyncMIDIPort::set_process_thread (pthread_t thr)
340 {
341         _process_thread = thr;
342 }
343
344 bool
345 AsyncMIDIPort::is_process_thread()
346 {
347         return pthread_equal (pthread_self(), _process_thread);
348 }
349