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