when destroying a MidiSource, invalidate any existing MidiCursors
[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.add_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->add_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first));
99                 child->add_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->add_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first));
105                 child->add_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         XMLProperty const * prop;
115         if ((prop = node.property ("captured-for")) != 0) {
116                 _captured_for = prop->value();
117         }
118
119         XMLNodeList children = node.children ();
120         for (XMLNodeConstIterator i = children.begin(); i != children.end(); ++i) {
121                 if ((*i)->name() == X_("InterpolationStyle")) {
122                         if ((prop = (*i)->property (X_("parameter"))) == 0) {
123                                 error << _("Missing parameter property on InterpolationStyle") << endmsg;
124                                 return -1;
125                         }
126                         Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value());
127
128                         if ((prop = (*i)->property (X_("style"))) == 0) {
129                                 error << _("Missing style property on InterpolationStyle") << endmsg;
130                                 return -1;
131                         }
132                         Evoral::ControlList::InterpolationStyle s = static_cast<Evoral::ControlList::InterpolationStyle>(
133                                 string_2_enum (prop->value(), s));
134                         set_interpolation_of (p, s);
135
136                 } else if ((*i)->name() == X_("AutomationState")) {
137                         if ((prop = (*i)->property (X_("parameter"))) == 0) {
138                                 error << _("Missing parameter property on AutomationState") << endmsg;
139                                 return -1;
140                         }
141                         Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value());
142
143                         if ((prop = (*i)->property (X_("state"))) == 0) {
144                                 error << _("Missing state property on AutomationState") << endmsg;
145                                 return -1;
146                         }
147                         AutoState s = static_cast<AutoState> (string_2_enum (prop->value(), s));
148                         set_automation_state_of (p, s);
149                 }
150         }
151
152         return 0;
153 }
154
155 bool
156 MidiSource::empty () const
157 {
158         return !_length_beats;
159 }
160
161 framecnt_t
162 MidiSource::length (framepos_t pos) const
163 {
164         if (!_length_beats) {
165                 return 0;
166         }
167
168         BeatsFramesConverter converter(_session.tempo_map(), pos);
169         return converter.to(_length_beats);
170 }
171
172 void
173 MidiSource::update_length (framecnt_t)
174 {
175         // You're not the boss of me!
176 }
177
178 void
179 MidiSource::invalidate (const Lock& lock)
180 {
181         Invalidated(_session.transport_rolling());
182 }
183
184 framecnt_t
185 MidiSource::midi_read (const Lock&                        lm,
186                        Evoral::EventSink<framepos_t>&     dst,
187                        framepos_t                         source_start,
188                        framepos_t                         start,
189                        framecnt_t                         cnt,
190                        Evoral::Range<framepos_t>*         loop_range,
191                        MidiCursor&                        cursor,
192                        MidiStateTracker*                  tracker,
193                        MidiChannelFilter*                 filter,
194                        const std::set<Evoral::Parameter>& filtered,
195                        const double                       pos_beats,
196                        const double                       start_beats) const
197 {
198         BeatsFramesConverter converter(_session.tempo_map(), source_start);
199
200         const double start_qn = pos_beats - start_beats;
201
202         DEBUG_TRACE (DEBUG::MidiSourceIO,
203                      string_compose ("MidiSource::midi_read() %5 sstart %1 start %2 cnt %3 tracker %4\n",
204                                      source_start, start, cnt, tracker, name()));
205
206         if (!_model) {
207                 return read_unlocked (lm, dst, source_start, start, cnt, loop_range, tracker, filter);
208         }
209
210         // Find appropriate model iterator
211         Evoral::Sequence<Evoral::Beats>::const_iterator& i = cursor.iter;
212         const bool linear_read = cursor.last_read_end != 0 && start == cursor.last_read_end;
213         if (!linear_read || !i.valid()) {
214                 /* Cached iterator is invalid, search for the first event past start.
215                    Note that multiple tracks can use a MidiSource simultaneously, so
216                    all playback state must be in parameters (the cursor) and must not
217                    be cached in the source of model itself.
218                    See http://tracker.ardour.org/view.php?id=6541
219                 */
220                 cursor.connect(Invalidated);
221                 cursor.iter = _model->begin(converter.from(start), false, filtered, &cursor.active_notes);
222                 cursor.active_notes.clear();
223         }
224
225         cursor.last_read_end = start + cnt;
226
227         // Copy events in [start, start + cnt) into dst
228         for (; i != _model->end(); ++i) {
229
230                 // Offset by source start to convert event time to session time
231
232                 framepos_t time_frames = _session.tempo_map().frame_at_quarter_note (i->time().to_double() + start_qn);
233
234                 if (time_frames < start + source_start) {
235                         /* event too early */
236
237                         continue;
238
239                 } else if (time_frames >= start + cnt + source_start) {
240
241                         DEBUG_TRACE (DEBUG::MidiSourceIO,
242                                      string_compose ("%1: reached end with event @ %2 vs. %3\n",
243                                                      _name, time_frames, start+cnt));
244                         break;
245
246                 } else {
247
248                         /* in range */
249
250                         if (loop_range) {
251                                 time_frames = loop_range->squish (time_frames);
252                         }
253
254                         const uint8_t status           = i->buffer()[0];
255                         const bool    is_channel_event = (0x80 <= (status & 0xF0)) && (status <= 0xE0);
256                         if (filter && is_channel_event) {
257                                 /* Copy event so the filter can modify the channel.  I'm not
258                                    sure if this is necessary here (channels are mapped later in
259                                    buffers anyway), but it preserves existing behaviour without
260                                    destroying events in the model during read. */
261                                 Evoral::Event<Evoral::Beats> ev(*i, true);
262                                 if (!filter->filter(ev.buffer(), ev.size())) {
263                                         dst.write(time_frames, ev.event_type(), ev.size(), ev.buffer());
264                                 } else {
265                                         DEBUG_TRACE (DEBUG::MidiSourceIO,
266                                                      string_compose ("%1: filter event @ %2 type %3 size %4\n",
267                                                                      _name, time_frames, i->event_type(), i->size()));
268                                 }
269                         } else {
270                                 dst.write (time_frames, i->event_type(), i->size(), i->buffer());
271                         }
272
273 #ifndef NDEBUG
274                         if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) {
275                                 DEBUG_STR_DECL(a);
276                                 DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 sz %3 within %4 .. %5 ",
277                                                                     _name, time_frames, i->size(),
278                                                                     start + source_start, start + cnt + source_start));
279                                 for (size_t n=0; n < i->size(); ++n) {
280                                         DEBUG_STR_APPEND(a,hex);
281                                         DEBUG_STR_APPEND(a,"0x");
282                                         DEBUG_STR_APPEND(a,(int)i->buffer()[n]);
283                                         DEBUG_STR_APPEND(a,' ');
284                                 }
285                                 DEBUG_STR_APPEND(a,'\n');
286                                 DEBUG_TRACE (DEBUG::MidiSourceIO, DEBUG_STR(a).str());
287                         }
288 #endif
289
290                         if (tracker) {
291                                 tracker->track (*i);
292                         }
293                 }
294         }
295
296         return cnt;
297 }
298
299 framecnt_t
300 MidiSource::midi_write (const Lock&                 lm,
301                         MidiRingBuffer<framepos_t>& source,
302                         framepos_t                  source_start,
303                         framecnt_t                  cnt)
304 {
305         const framecnt_t ret = write_unlocked (lm, source, source_start, cnt);
306
307         if (cnt == max_framecnt) {
308                 invalidate(lm);
309         } else {
310                 _capture_length += cnt;
311         }
312
313         return ret;
314 }
315
316 void
317 MidiSource::mark_streaming_midi_write_started (const Lock& lock, NoteMode mode)
318 {
319         if (_model) {
320                 _model->set_note_mode (mode);
321                 _model->start_write ();
322         }
323
324         _writing = true;
325 }
326
327 void
328 MidiSource::mark_write_starting_now (framecnt_t position,
329                                      framecnt_t capture_length,
330                                      framecnt_t loop_length)
331 {
332         /* I'm not sure if this is the best way to approach this, but
333            _capture_length needs to be set up with the transport frame
334            when a record actually starts, as it is used by
335            SMFSource::write_unlocked to decide whether incoming notes
336            are within the correct time range.
337            mark_streaming_midi_write_started (perhaps a more logical
338            place to do this) is not called at exactly the time when
339            record starts, and I don't think it necessarily can be
340            because it is not RT-safe.
341         */
342
343         set_timeline_position(position);
344         _capture_length      = capture_length;
345         _capture_loop_length = loop_length;
346
347         TempoMap& map (_session.tempo_map());
348         BeatsFramesConverter converter(map, position);
349         _length_beats = converter.from(capture_length);
350 }
351
352 void
353 MidiSource::mark_streaming_write_started (const Lock& lock)
354 {
355         NoteMode note_mode = _model ? _model->note_mode() : Sustained;
356         mark_streaming_midi_write_started (lock, note_mode);
357 }
358
359 void
360 MidiSource::mark_midi_streaming_write_completed (const Lock&                                      lock,
361                                                  Evoral::Sequence<Evoral::Beats>::StuckNoteOption option,
362                                                  Evoral::Beats                                    end)
363 {
364         if (_model) {
365                 _model->end_write (option, end);
366
367                 /* Make captured controls discrete to play back user input exactly. */
368                 for (MidiModel::Controls::iterator i = _model->controls().begin(); i != _model->controls().end(); ++i) {
369                         if (i->second->list()) {
370                                 i->second->list()->set_interpolation(Evoral::ControlList::Discrete);
371                                 _interpolation_style.insert(std::make_pair(i->second->parameter(), Evoral::ControlList::Discrete));
372                         }
373                 }
374         }
375
376         invalidate(lock);
377         _writing = false;
378 }
379
380 void
381 MidiSource::mark_streaming_write_completed (const Lock& lock)
382 {
383         mark_midi_streaming_write_completed (lock, Evoral::Sequence<Evoral::Beats>::DeleteStuckNotes);
384 }
385
386 int
387 MidiSource::export_write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Evoral::Beats begin, Evoral::Beats end)
388 {
389         Lock newsrc_lock (newsrc->mutex ());
390
391         if (!_model) {
392                 error << string_compose (_("programming error: %1"), X_("no model for MidiSource during export"));
393                 return -1;
394         }
395
396         _model->write_section_to (newsrc, newsrc_lock, begin, end, true);
397
398         newsrc->flush_midi(newsrc_lock);
399
400         return 0;
401 }
402
403 int
404 MidiSource::write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Evoral::Beats begin, Evoral::Beats end)
405 {
406         Lock newsrc_lock (newsrc->mutex ());
407
408         newsrc->set_timeline_position (_timeline_position);
409         newsrc->copy_interpolation_from (this);
410         newsrc->copy_automation_state_from (this);
411
412         if (_model) {
413                 if (begin == Evoral::MinBeats && end == Evoral::MaxBeats) {
414                         _model->write_to (newsrc, newsrc_lock);
415                 } else {
416                         _model->write_section_to (newsrc, newsrc_lock, begin, end);
417                 }
418         } else {
419                 error << string_compose (_("programming error: %1"), X_("no model for MidiSource during ::clone()"));
420                 return -1;
421         }
422
423         newsrc->flush_midi(newsrc_lock);
424
425         /* force a reload of the model if the range is partial */
426
427         if (begin != Evoral::MinBeats || end != Evoral::MaxBeats) {
428                 newsrc->load_model (newsrc_lock, true);
429         } else {
430                 newsrc->set_model (newsrc_lock, _model);
431         }
432
433         /* this file is not removable (but since it is MIDI, it is mutable) */
434
435         boost::dynamic_pointer_cast<FileSource> (newsrc)->prevent_deletion ();
436
437         return 0;
438 }
439
440 void
441 MidiSource::session_saved()
442 {
443         Lock lm (_lock);
444
445         /* this writes a copy of the data to disk.
446            XXX do we need to do this every time?
447         */
448
449         if (_model && _model->edited()) {
450                 /* The model is edited, write its contents into the current source
451                    file (overwiting previous contents). */
452
453                 /* Temporarily drop our reference to the model so that as the model
454                    pushes its current state to us, we don't try to update it. */
455                 boost::shared_ptr<MidiModel> mm = _model;
456                 _model.reset ();
457
458                 /* Flush model contents to disk. */
459                 mm->sync_to_source (lm);
460
461                 /* Reacquire model. */
462                 _model = mm;
463
464         } else {
465                 flush_midi(lm);
466         }
467 }
468
469 void
470 MidiSource::set_note_mode(const Lock& lock, NoteMode mode)
471 {
472         if (_model) {
473                 _model->set_note_mode(mode);
474         }
475 }
476
477 void
478 MidiSource::drop_model (const Lock& lock)
479 {
480         _model.reset();
481         invalidate(lock);
482         ModelChanged (); /* EMIT SIGNAL */
483 }
484
485 void
486 MidiSource::set_model (const Lock& lock, boost::shared_ptr<MidiModel> m)
487 {
488         _model = m;
489         invalidate(lock);
490         ModelChanged (); /* EMIT SIGNAL */
491 }
492
493 Evoral::ControlList::InterpolationStyle
494 MidiSource::interpolation_of (Evoral::Parameter p) const
495 {
496         InterpolationStyleMap::const_iterator i = _interpolation_style.find (p);
497         if (i == _interpolation_style.end()) {
498                 return EventTypeMap::instance().interpolation_of (p);
499         }
500
501         return i->second;
502 }
503
504 AutoState
505 MidiSource::automation_state_of (Evoral::Parameter p) const
506 {
507         AutomationStateMap::const_iterator i = _automation_state.find (p);
508         if (i == _automation_state.end()) {
509                 /* default to `play', otherwise if MIDI is recorded /
510                    imported with controllers etc. they are by default
511                    not played back, which is a little surprising.
512                 */
513                 return Play;
514         }
515
516         return i->second;
517 }
518
519 /** Set interpolation style to be used for a given parameter.  This change will be
520  *  propagated to anyone who needs to know.
521  */
522 void
523 MidiSource::set_interpolation_of (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
524 {
525         if (interpolation_of (p) == s) {
526                 return;
527         }
528
529         if (EventTypeMap::instance().interpolation_of (p) == s) {
530                 /* interpolation type is being set to the default, so we don't need a note in our map */
531                 _interpolation_style.erase (p);
532         } else {
533                 _interpolation_style[p] = s;
534         }
535
536         InterpolationChanged (p, s); /* EMIT SIGNAL */
537 }
538
539 void
540 MidiSource::set_automation_state_of (Evoral::Parameter p, AutoState s)
541 {
542         if (automation_state_of (p) == s) {
543                 return;
544         }
545
546         if (s == Play) {
547                 /* automation state is being set to the default, so we don't need a note in our map */
548                 _automation_state.erase (p);
549         } else {
550                 _automation_state[p] = s;
551         }
552
553         AutomationStateChanged (p, s); /* EMIT SIGNAL */
554 }
555
556 void
557 MidiSource::copy_interpolation_from (boost::shared_ptr<MidiSource> s)
558 {
559         copy_interpolation_from (s.get ());
560 }
561
562 void
563 MidiSource::copy_automation_state_from (boost::shared_ptr<MidiSource> s)
564 {
565         copy_automation_state_from (s.get ());
566 }
567
568 void
569 MidiSource::copy_interpolation_from (MidiSource* s)
570 {
571         _interpolation_style = s->_interpolation_style;
572
573         /* XXX: should probably emit signals here */
574 }
575
576 void
577 MidiSource::copy_automation_state_from (MidiSource* s)
578 {
579         _automation_state = s->_automation_state;
580
581         /* XXX: should probably emit signals here */
582 }