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