use a note tracker to resolve notes cut off during render by the end of the region
[ardour.git] / libs / ardour / midi_source.cc
1 /*
2  * Copyright (C) 2006-2016 David Robillard <d@drobilla.net>
3  * Copyright (C) 2007-2018 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
5  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
6  * Copyright (C) 2012-2016 Tim Mayberry <mojofunk@gmail.com>
7  * Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org>
8  * Copyright (C) 2016 Nick Mainsbridge <mainsbridge@gmail.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <float.h>
29 #include <cerrno>
30 #include <ctime>
31 #include <cmath>
32 #include <iomanip>
33 #include <algorithm>
34
35 #include <glibmm/fileutils.h>
36 #include <glibmm/miscutils.h>
37
38 #include "pbd/xml++.h"
39 #include "pbd/pthread_utils.h"
40 #include "pbd/basename.h"
41 #include "pbd/timing.h"
42
43 #include "evoral/Control.hpp"
44 #include "evoral/EventSink.hpp"
45
46 #include "ardour/debug.h"
47 #include "ardour/file_source.h"
48 #include "ardour/midi_channel_filter.h"
49 #include "ardour/midi_cursor.h"
50 #include "ardour/midi_model.h"
51 #include "ardour/midi_source.h"
52 #include "ardour/midi_state_tracker.h"
53 #include "ardour/session.h"
54 #include "ardour/session_directory.h"
55 #include "ardour/source_factory.h"
56 #include "ardour/tempo.h"
57
58 #include "pbd/i18n.h"
59
60 namespace ARDOUR { template <typename T> class MidiRingBuffer; }
61
62 using namespace std;
63 using namespace ARDOUR;
64 using namespace PBD;
65
66 MidiSource::MidiSource (Session& s, string name, Source::Flag flags)
67         : Source(s, DataType::MIDI, name, flags)
68         , _writing(false)
69         , _length_beats(0.0)
70         , _capture_length(0)
71         , _capture_loop_length(0)
72 {
73 }
74
75 MidiSource::MidiSource (Session& s, const XMLNode& node)
76         : Source(s, node)
77         , _writing(false)
78         , _length_beats(0.0)
79         , _capture_length(0)
80         , _capture_loop_length(0)
81 {
82         if (set_state (node, Stateful::loading_state_version)) {
83                 throw failed_constructor();
84         }
85 }
86
87 MidiSource::~MidiSource ()
88 {
89         /* invalidate any existing iterators */
90         Invalidated (false);
91 }
92
93 XMLNode&
94 MidiSource::get_state ()
95 {
96         XMLNode& node (Source::get_state());
97
98         if (_captured_for.length()) {
99                 node.set_property ("captured-for", _captured_for);
100         }
101
102         for (InterpolationStyleMap::const_iterator i = _interpolation_style.begin(); i != _interpolation_style.end(); ++i) {
103                 XMLNode* child = node.add_child (X_("InterpolationStyle"));
104                 child->set_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first));
105                 child->set_property (X_("style"), enum_2_string (i->second));
106         }
107
108         for (AutomationStateMap::const_iterator i = _automation_state.begin(); i != _automation_state.end(); ++i) {
109                 XMLNode* child = node.add_child (X_("AutomationState"));
110                 child->set_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first));
111                 child->set_property (X_("state"), enum_2_string (i->second));
112         }
113
114         return node;
115 }
116
117 int
118 MidiSource::set_state (const XMLNode& node, int /*version*/)
119 {
120         node.get_property ("captured-for", _captured_for);
121
122         std::string str;
123         XMLNodeList children = node.children ();
124         for (XMLNodeConstIterator i = children.begin(); i != children.end(); ++i) {
125                 if ((*i)->name() == X_("InterpolationStyle")) {
126                         if (!(*i)->get_property (X_("parameter"), str)) {
127                                 error << _("Missing parameter property on InterpolationStyle") << endmsg;
128                                 return -1;
129                         }
130                         Evoral::Parameter p = EventTypeMap::instance().from_symbol (str);
131
132                         switch (p.type()) {
133                         case MidiCCAutomation:
134                         case MidiPgmChangeAutomation:       break;
135                         case MidiChannelPressureAutomation: break;
136                         case MidiNotePressureAutomation:    break;
137                         case MidiPitchBenderAutomation:     break;
138                         case MidiSystemExclusiveAutomation:
139                                 cerr << "Parameter \"" << str << "\" is system exclusive - no automation possible!\n";
140                                 continue;
141                         default:
142                                 cerr << "Parameter \"" << str << "\" found for MIDI source ... not legal; ignoring this parameter\n";
143                                 continue;
144                         }
145
146                         if (!(*i)->get_property (X_("style"), str)) {
147                                 error << _("Missing style property on InterpolationStyle") << endmsg;
148                                 return -1;
149                         }
150                         Evoral::ControlList::InterpolationStyle s =
151                             static_cast<Evoral::ControlList::InterpolationStyle>(string_2_enum (str, s));
152                         set_interpolation_of (p, s);
153
154                 } else if ((*i)->name() == X_("AutomationState")) {
155                         if (!(*i)->get_property (X_("parameter"), str)) {
156                                 error << _("Missing parameter property on AutomationState") << endmsg;
157                                 return -1;
158                         }
159                         Evoral::Parameter p = EventTypeMap::instance().from_symbol (str);
160
161                         if (!(*i)->get_property (X_("state"), str)) {
162                                 error << _("Missing state property on AutomationState") << endmsg;
163                                 return -1;
164                         }
165                         AutoState s = static_cast<AutoState>(string_2_enum (str, s));
166                         set_automation_state_of (p, s);
167                 }
168         }
169
170         return 0;
171 }
172
173 bool
174 MidiSource::empty () const
175 {
176         return !_length_beats;
177 }
178
179 samplecnt_t
180 MidiSource::length (samplepos_t pos) const
181 {
182         if (!_length_beats) {
183                 return 0;
184         }
185
186         BeatsSamplesConverter converter(_session.tempo_map(), pos);
187         return converter.to(_length_beats);
188 }
189
190 void
191 MidiSource::update_length (samplecnt_t)
192 {
193         // You're not the boss of me!
194 }
195
196 void
197 MidiSource::invalidate (const Lock& lock)
198 {
199         Invalidated(_session.transport_rolling());
200 }
201
202 samplecnt_t
203 MidiSource::midi_read (const Lock&                        lm,
204                        Evoral::EventSink<samplepos_t>&    dst,
205                        samplepos_t                        source_start,
206                        samplepos_t                        start,
207                        samplecnt_t                        cnt,
208                        Evoral::Range<samplepos_t>*        loop_range,
209                        MidiCursor&                        cursor,
210                        MidiStateTracker*                  tracker,
211                        MidiChannelFilter*                 filter,
212                        const std::set<Evoral::Parameter>& filtered,
213                        const double                       pos_beats,
214                        const double                       start_beats) const
215 {
216         BeatsSamplesConverter converter(_session.tempo_map(), source_start);
217
218         const double start_qn = pos_beats - start_beats;
219
220         DEBUG_TRACE (DEBUG::MidiSourceIO,
221                      string_compose ("MidiSource::midi_read() %5 sstart %1 start %2 cnt %3 tracker %4\n",
222                                      source_start, start, cnt, tracker, name()));
223
224         if (!_model) {
225                 return read_unlocked (lm, dst, source_start, start, cnt, loop_range, tracker, filter);
226         }
227
228         // Find appropriate model iterator
229         Evoral::Sequence<Temporal::Beats>::const_iterator& i = cursor.iter;
230         const bool linear_read = cursor.last_read_end != 0 && start == cursor.last_read_end;
231         if (!linear_read || !i.valid()) {
232                 /* Cached iterator is invalid, search for the first event past start.
233                    Note that multiple tracks can use a MidiSource simultaneously, so
234                    all playback state must be in parameters (the cursor) and must not
235                    be cached in the source of model itself.
236                    See http://tracker.ardour.org/view.php?id=6541
237                 */
238                 cursor.connect(Invalidated);
239                 cursor.iter = _model->begin(converter.from(start), false, filtered, &cursor.active_notes);
240                 cursor.active_notes.clear();
241         }
242
243         cursor.last_read_end = start + cnt;
244
245         samplepos_t time_samples = 0;
246         // Copy events in [start, start + cnt) into dst
247         for (; i != _model->end(); ++i) {
248
249                 // Offset by source start to convert event time to session time
250
251                 samplepos_t time_samples = _session.tempo_map().sample_at_quarter_note (i->time().to_double() + start_qn);
252
253                 if (time_samples < start + source_start) {
254                         /* event too early */
255
256                         continue;
257
258                 } else if (time_samples >= start + cnt + source_start) {
259
260                         DEBUG_TRACE (DEBUG::MidiSourceIO,
261                                      string_compose ("%1: reached end with event @ %2 vs. %3\n",
262                                                      _name, time_samples, start+cnt));
263                         break;
264
265                 } else {
266
267                         /* in range */
268
269                         if (loop_range) {
270                                 time_samples = loop_range->squish (time_samples);
271                         }
272
273                         const uint8_t status           = i->buffer()[0];
274                         const bool    is_channel_event = (0x80 <= (status & 0xF0)) && (status <= 0xE0);
275                         if (filter && is_channel_event) {
276                                 /* Copy event so the filter can modify the channel.  I'm not
277                                    sure if this is necessary here (channels are mapped later in
278                                    buffers anyway), but it preserves existing behaviour without
279                                    destroying events in the model during read. */
280                                 Evoral::Event<Temporal::Beats> ev(*i, true);
281                                 if (!filter->filter(ev.buffer(), ev.size())) {
282                                         dst.write (time_samples, ev.event_type(), ev.size(), ev.buffer());
283                                 } else {
284                                         DEBUG_TRACE (DEBUG::MidiSourceIO,
285                                                      string_compose ("%1: filter event @ %2 type %3 size %4\n",
286                                                                      _name, time_samples, i->event_type(), i->size()));
287                                 }
288                         } else {
289                                 dst.write (time_samples, i->event_type(), i->size(), i->buffer());
290                         }
291
292 #ifndef NDEBUG
293                         if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) {
294                                 DEBUG_STR_DECL(a);
295                                 DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 sz %3 within %4 .. %5 ",
296                                                                     _name, time_samples, i->size(),
297                                                                     start + source_start, start + cnt + source_start));
298                                 for (size_t n=0; n < i->size(); ++n) {
299                                         DEBUG_STR_APPEND(a,hex);
300                                         DEBUG_STR_APPEND(a,"0x");
301                                         DEBUG_STR_APPEND(a,(int)i->buffer()[n]);
302                                         DEBUG_STR_APPEND(a,' ');
303                                 }
304                                 DEBUG_STR_APPEND(a,'\n');
305                                 DEBUG_TRACE (DEBUG::MidiSourceIO, DEBUG_STR(a).str());
306                         }
307 #endif
308
309                         if (tracker) {
310                                 tracker->track (*i);
311                         }
312                 }
313         }
314
315         return cnt;
316 }
317
318 samplecnt_t
319 MidiSource::midi_write (const Lock&                  lm,
320                         MidiRingBuffer<samplepos_t>& source,
321                         samplepos_t                  source_start,
322                         samplecnt_t                  cnt)
323 {
324         const samplecnt_t ret = write_unlocked (lm, source, source_start, cnt);
325
326         if (cnt == max_samplecnt) {
327                 invalidate(lm);
328         } else {
329                 _capture_length += cnt;
330         }
331
332         return ret;
333 }
334
335 void
336 MidiSource::mark_streaming_midi_write_started (const Lock& lock, NoteMode mode)
337 {
338         if (_model) {
339                 _model->set_note_mode (mode);
340                 _model->start_write ();
341         }
342
343         _writing = true;
344 }
345
346 void
347 MidiSource::mark_write_starting_now (samplecnt_t position,
348                                      samplecnt_t capture_length,
349                                      samplecnt_t loop_length)
350 {
351         /* I'm not sure if this is the best way to approach this, but
352            _capture_length needs to be set up with the transport sample
353            when a record actually starts, as it is used by
354            SMFSource::write_unlocked to decide whether incoming notes
355            are within the correct time range.
356            mark_streaming_midi_write_started (perhaps a more logical
357            place to do this) is not called at exactly the time when
358            record starts, and I don't think it necessarily can be
359            because it is not RT-safe.
360         */
361
362         set_natural_position (position);
363         _capture_length      = capture_length;
364         _capture_loop_length = loop_length;
365
366         TempoMap& map (_session.tempo_map());
367         BeatsSamplesConverter converter(map, position);
368         _length_beats = converter.from(capture_length);
369 }
370
371 void
372 MidiSource::mark_streaming_write_started (const Lock& lock)
373 {
374         NoteMode note_mode = _model ? _model->note_mode() : Sustained;
375         mark_streaming_midi_write_started (lock, note_mode);
376 }
377
378 void
379 MidiSource::mark_midi_streaming_write_completed (const Lock&                                        lock,
380                                                  Evoral::Sequence<Temporal::Beats>::StuckNoteOption option,
381                                                  Temporal::Beats                                    end)
382 {
383         if (_model) {
384                 _model->end_write (option, end);
385
386                 /* Make captured controls discrete to play back user input exactly. */
387                 for (MidiModel::Controls::iterator i = _model->controls().begin(); i != _model->controls().end(); ++i) {
388                         if (i->second->list()) {
389                                 i->second->list()->set_interpolation(Evoral::ControlList::Discrete);
390                                 _interpolation_style.insert(std::make_pair(i->second->parameter(), Evoral::ControlList::Discrete));
391                         }
392                 }
393         }
394
395         invalidate(lock);
396         _writing = false;
397 }
398
399 void
400 MidiSource::mark_streaming_write_completed (const Lock& lock)
401 {
402         mark_midi_streaming_write_completed (lock, Evoral::Sequence<Temporal::Beats>::DeleteStuckNotes);
403 }
404
405 int
406 MidiSource::export_write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Temporal::Beats begin, Temporal::Beats end)
407 {
408         Lock newsrc_lock (newsrc->mutex ());
409
410         if (!_model) {
411                 error << string_compose (_("programming error: %1"), X_("no model for MidiSource during export"));
412                 return -1;
413         }
414
415         _model->write_section_to (newsrc, newsrc_lock, begin, end, true);
416
417         newsrc->flush_midi(newsrc_lock);
418
419         return 0;
420 }
421
422 int
423 MidiSource::write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Temporal::Beats begin, Temporal::Beats end)
424 {
425         Lock newsrc_lock (newsrc->mutex ());
426
427         newsrc->set_natural_position (_natural_position);
428         newsrc->copy_interpolation_from (this);
429         newsrc->copy_automation_state_from (this);
430
431         if (_model) {
432                 if (begin == Temporal::Beats() && end == std::numeric_limits<Temporal::Beats>::max()) {
433                         _model->write_to (newsrc, newsrc_lock);
434                 } else {
435                         _model->write_section_to (newsrc, newsrc_lock, begin, end);
436                 }
437         } else {
438                 error << string_compose (_("programming error: %1"), X_("no model for MidiSource during ::clone()"));
439                 return -1;
440         }
441
442         newsrc->flush_midi(newsrc_lock);
443
444         /* force a reload of the model if the range is partial */
445
446         if (begin != Temporal::Beats() || end != std::numeric_limits<Temporal::Beats>::max()) {
447                 newsrc->load_model (newsrc_lock, true);
448         } else {
449                 newsrc->set_model (newsrc_lock, _model);
450         }
451
452         /* this file is not removable (but since it is MIDI, it is mutable) */
453
454         boost::dynamic_pointer_cast<FileSource> (newsrc)->prevent_deletion ();
455
456         return 0;
457 }
458
459 void
460 MidiSource::session_saved()
461 {
462         Lock lm (_lock);
463
464         /* this writes a copy of the data to disk.
465            XXX do we need to do this every time?
466         */
467
468         if (_model && _model->edited()) {
469                 /* The model is edited, write its contents into the current source
470                    file (overwiting previous contents). */
471
472                 /* Temporarily drop our reference to the model so that as the model
473                    pushes its current state to us, we don't try to update it. */
474                 boost::shared_ptr<MidiModel> mm = _model;
475                 _model.reset ();
476
477                 /* Flush model contents to disk. */
478                 mm->sync_to_source (lm);
479
480                 /* Reacquire model. */
481                 _model = mm;
482
483         } else {
484                 flush_midi(lm);
485         }
486 }
487
488 void
489 MidiSource::set_note_mode(const Lock& lock, NoteMode mode)
490 {
491         if (_model) {
492                 _model->set_note_mode(mode);
493         }
494 }
495
496 void
497 MidiSource::drop_model (const Lock& lock)
498 {
499         _model.reset();
500         invalidate(lock);
501         ModelChanged (); /* EMIT SIGNAL */
502 }
503
504 void
505 MidiSource::set_model (const Lock& lock, boost::shared_ptr<MidiModel> m)
506 {
507         _model = m;
508         invalidate(lock);
509         ModelChanged (); /* EMIT SIGNAL */
510 }
511
512 Evoral::ControlList::InterpolationStyle
513 MidiSource::interpolation_of (Evoral::Parameter p) const
514 {
515         InterpolationStyleMap::const_iterator i = _interpolation_style.find (p);
516         if (i == _interpolation_style.end()) {
517                 return EventTypeMap::instance().interpolation_of (p);
518         }
519
520         return i->second;
521 }
522
523 AutoState
524 MidiSource::automation_state_of (Evoral::Parameter p) const
525 {
526         AutomationStateMap::const_iterator i = _automation_state.find (p);
527         if (i == _automation_state.end()) {
528                 /* default to `play', otherwise if MIDI is recorded /
529                    imported with controllers etc. they are by default
530                    not played back, which is a little surprising.
531                 */
532                 return Play;
533         }
534
535         return i->second;
536 }
537
538 /** Set interpolation style to be used for a given parameter.  This change will be
539  *  propagated to anyone who needs to know.
540  */
541 void
542 MidiSource::set_interpolation_of (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
543 {
544         if (interpolation_of (p) == s) {
545                 return;
546         }
547
548         if (EventTypeMap::instance().interpolation_of (p) == s) {
549                 /* interpolation type is being set to the default, so we don't need a note in our map */
550                 _interpolation_style.erase (p);
551         } else {
552                 _interpolation_style[p] = s;
553         }
554
555         InterpolationChanged (p, s); /* EMIT SIGNAL */
556 }
557
558 void
559 MidiSource::set_automation_state_of (Evoral::Parameter p, AutoState s)
560 {
561         if (automation_state_of (p) == s) {
562                 return;
563         }
564
565         if (s == Play) {
566                 /* automation state is being set to the default, so we don't need a note in our map */
567                 _automation_state.erase (p);
568         } else {
569                 _automation_state[p] = s;
570         }
571
572         AutomationStateChanged (p, s); /* EMIT SIGNAL */
573 }
574
575 void
576 MidiSource::copy_interpolation_from (boost::shared_ptr<MidiSource> s)
577 {
578         copy_interpolation_from (s.get ());
579 }
580
581 void
582 MidiSource::copy_automation_state_from (boost::shared_ptr<MidiSource> s)
583 {
584         copy_automation_state_from (s.get ());
585 }
586
587 void
588 MidiSource::copy_interpolation_from (MidiSource* s)
589 {
590         _interpolation_style = s->_interpolation_style;
591
592         /* XXX: should probably emit signals here */
593 }
594
595 void
596 MidiSource::copy_automation_state_from (MidiSource* s)
597 {
598         _automation_state = s->_automation_state;
599
600         /* XXX: should probably emit signals here */
601 }