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.h"
44 #include "evoral/EventSink.h"
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 
MidiSource(Session & s,string name,Source::Flag flags)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 
MidiSource(Session & s,const XMLNode & node)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 
~MidiSource()87 MidiSource::~MidiSource ()
88 {
89 	/* invalidate any existing iterators */
90 	Invalidated (false);
91 }
92 
93 XMLNode&
get_state()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
set_state(const XMLNode & node,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
empty() const174 MidiSource::empty () const
175 {
176 	return !_length_beats;
177 }
178 
179 samplecnt_t
length(samplepos_t pos) const180 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
update_length(samplecnt_t)191 MidiSource::update_length (samplecnt_t)
192 {
193 	// You're not the boss of me!
194 }
195 
196 void
invalidate(const Lock & lock)197 MidiSource::invalidate (const Lock& lock)
198 {
199 	Invalidated(_session.transport_rolling());
200 }
201 
202 samplecnt_t
midi_read(const Lock & lm,Evoral::EventSink<samplepos_t> & dst,samplepos_t source_start,samplepos_t start,samplecnt_t cnt,Evoral::Range<samplepos_t> * loop_range,MidiCursor & cursor,MidiStateTracker * tracker,MidiChannelFilter * filter,const std::set<Evoral::Parameter> & filtered,const double pos_beats,const double start_beats) const203 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 	// Copy events in [start, start + cnt) into dst
246 	for (; i != _model->end(); ++i) {
247 
248 		// Offset by source start to convert event time to session time
249 
250 		samplepos_t time_samples = _session.tempo_map().sample_at_quarter_note (i->time().to_double() + start_qn);
251 
252 		if (time_samples < start + source_start) {
253 			/* event too early */
254 
255 			continue;
256 
257 		} else if (time_samples >= start + cnt + source_start) {
258 
259 			DEBUG_TRACE (DEBUG::MidiSourceIO,
260 			             string_compose ("%1: reached end with event @ %2 vs. %3\n",
261 			                             _name, time_samples, start+cnt));
262 			break;
263 
264 		} else {
265 
266 			/* in range */
267 
268 			if (loop_range) {
269 				time_samples = loop_range->squish (time_samples);
270 			}
271 
272 			const uint8_t status           = i->buffer()[0];
273 			const bool    is_channel_event = (0x80 <= (status & 0xF0)) && (status <= 0xE0);
274 			if (filter && is_channel_event) {
275 				/* Copy event so the filter can modify the channel.  I'm not
276 				   sure if this is necessary here (channels are mapped later in
277 				   buffers anyway), but it preserves existing behaviour without
278 				   destroying events in the model during read. */
279 				Evoral::Event<Temporal::Beats> ev(*i, true);
280 				if (!filter->filter(ev.buffer(), ev.size())) {
281 					dst.write (time_samples, ev.event_type(), ev.size(), ev.buffer());
282 				} else {
283 					DEBUG_TRACE (DEBUG::MidiSourceIO,
284 					             string_compose ("%1: filter event @ %2 type %3 size %4\n",
285 					                             _name, time_samples, i->event_type(), i->size()));
286 				}
287 			} else {
288 				dst.write (time_samples, i->event_type(), i->size(), i->buffer());
289 			}
290 
291 #ifndef NDEBUG
292 			if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) {
293 				DEBUG_STR_DECL(a);
294 				DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 sz %3 within %4 .. %5 ",
295 				                                    _name, time_samples, i->size(),
296 				                                    start + source_start, start + cnt + source_start));
297 				for (size_t n=0; n < i->size(); ++n) {
298 					DEBUG_STR_APPEND(a,hex);
299 					DEBUG_STR_APPEND(a,"0x");
300 					DEBUG_STR_APPEND(a,(int)i->buffer()[n]);
301 					DEBUG_STR_APPEND(a,' ');
302 				}
303 				DEBUG_STR_APPEND(a,'\n');
304 				DEBUG_TRACE (DEBUG::MidiSourceIO, DEBUG_STR(a).str());
305 			}
306 #endif
307 
308 			if (tracker) {
309 				tracker->track (*i);
310 			}
311 		}
312 	}
313 
314 	return cnt;
315 }
316 
317 samplecnt_t
midi_write(const Lock & lm,MidiRingBuffer<samplepos_t> & source,samplepos_t source_start,samplecnt_t cnt)318 MidiSource::midi_write (const Lock&                  lm,
319                         MidiRingBuffer<samplepos_t>& source,
320                         samplepos_t                  source_start,
321                         samplecnt_t                  cnt)
322 {
323 	const samplecnt_t ret = write_unlocked (lm, source, source_start, cnt);
324 
325 	if (cnt == max_samplecnt) {
326 		invalidate(lm);
327 	} else {
328 		_capture_length += cnt;
329 	}
330 
331 	return ret;
332 }
333 
334 void
mark_streaming_midi_write_started(const Lock & lock,NoteMode mode)335 MidiSource::mark_streaming_midi_write_started (const Lock& lock, NoteMode mode)
336 {
337 	if (_model) {
338 		_model->set_note_mode (mode);
339 		_model->start_write ();
340 	}
341 
342 	_writing = true;
343 }
344 
345 void
mark_write_starting_now(samplecnt_t position,samplecnt_t capture_length,samplecnt_t loop_length)346 MidiSource::mark_write_starting_now (samplecnt_t position,
347                                      samplecnt_t capture_length,
348                                      samplecnt_t loop_length)
349 {
350 	/* I'm not sure if this is the best way to approach this, but
351 	   _capture_length needs to be set up with the transport sample
352 	   when a record actually starts, as it is used by
353 	   SMFSource::write_unlocked to decide whether incoming notes
354 	   are within the correct time range.
355 	   mark_streaming_midi_write_started (perhaps a more logical
356 	   place to do this) is not called at exactly the time when
357 	   record starts, and I don't think it necessarily can be
358 	   because it is not RT-safe.
359 	*/
360 
361 	set_natural_position (position);
362 	_capture_length      = capture_length;
363 	_capture_loop_length = loop_length;
364 
365 	TempoMap& map (_session.tempo_map());
366 	BeatsSamplesConverter converter(map, position);
367 	_length_beats = converter.from(capture_length);
368 }
369 
370 void
mark_streaming_write_started(const Lock & lock)371 MidiSource::mark_streaming_write_started (const Lock& lock)
372 {
373 	NoteMode note_mode = _model ? _model->note_mode() : Sustained;
374 	mark_streaming_midi_write_started (lock, note_mode);
375 }
376 
377 void
mark_midi_streaming_write_completed(const Lock & lock,Evoral::Sequence<Temporal::Beats>::StuckNoteOption option,Temporal::Beats end)378 MidiSource::mark_midi_streaming_write_completed (const Lock&                                        lock,
379                                                  Evoral::Sequence<Temporal::Beats>::StuckNoteOption option,
380                                                  Temporal::Beats                                    end)
381 {
382 	if (_model) {
383 		_model->end_write (option, end);
384 
385 		/* Make captured controls discrete to play back user input exactly. */
386 		for (MidiModel::Controls::iterator i = _model->controls().begin(); i != _model->controls().end(); ++i) {
387 			if (i->second->list()) {
388 				i->second->list()->set_interpolation(Evoral::ControlList::Discrete);
389 				_interpolation_style.insert(std::make_pair(i->second->parameter(), Evoral::ControlList::Discrete));
390 			}
391 		}
392 	}
393 
394 	invalidate(lock);
395 	_writing = false;
396 }
397 
398 void
mark_streaming_write_completed(const Lock & lock)399 MidiSource::mark_streaming_write_completed (const Lock& lock)
400 {
401 	mark_midi_streaming_write_completed (lock, Evoral::Sequence<Temporal::Beats>::DeleteStuckNotes);
402 }
403 
404 int
export_write_to(const Lock & lock,boost::shared_ptr<MidiSource> newsrc,Temporal::Beats begin,Temporal::Beats end)405 MidiSource::export_write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Temporal::Beats begin, Temporal::Beats end)
406 {
407 	Lock newsrc_lock (newsrc->mutex ());
408 
409 	if (!_model) {
410 		error << string_compose (_("programming error: %1"), X_("no model for MidiSource during export"));
411 		return -1;
412 	}
413 
414 	_model->write_section_to (newsrc, newsrc_lock, begin, end, true);
415 
416 	newsrc->flush_midi(newsrc_lock);
417 
418 	return 0;
419 }
420 
421 int
write_to(const Lock & lock,boost::shared_ptr<MidiSource> newsrc,Temporal::Beats begin,Temporal::Beats end)422 MidiSource::write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Temporal::Beats begin, Temporal::Beats end)
423 {
424 	Lock newsrc_lock (newsrc->mutex ());
425 
426 	newsrc->set_natural_position (_natural_position);
427 	newsrc->copy_interpolation_from (this);
428 	newsrc->copy_automation_state_from (this);
429 
430 	if (_model) {
431 		if (begin == Temporal::Beats() && end == std::numeric_limits<Temporal::Beats>::max()) {
432 			_model->write_to (newsrc, newsrc_lock);
433 		} else {
434 			_model->write_section_to (newsrc, newsrc_lock, begin, end);
435 		}
436 	} else {
437 		error << string_compose (_("programming error: %1"), X_("no model for MidiSource during ::clone()"));
438 		return -1;
439 	}
440 
441 	newsrc->flush_midi(newsrc_lock);
442 
443 
444 	if (begin != Temporal::Beats() || end != std::numeric_limits<Temporal::Beats>::max()) {
445 		/* force a reload of the model if the range is partial */
446 		newsrc->load_model (newsrc_lock, true);
447 	} else {
448 		/* re-create model */
449 		newsrc->destroy_model (newsrc_lock);
450 		newsrc->load_model (newsrc_lock);
451 	}
452 
453 	/* this file is not removable (but since it is MIDI, it is mutable) */
454 
455 	boost::dynamic_pointer_cast<FileSource> (newsrc)->prevent_deletion ();
456 
457 	return 0;
458 }
459 
460 void
session_saved()461 MidiSource::session_saved()
462 {
463 	Lock lm (_lock);
464 
465 	/* this writes a copy of the data to disk.
466 	   XXX do we need to do this every time?
467 	*/
468 
469 	if (_model && _model->edited()) {
470 		/* The model is edited, write its contents into the current source
471 		   file (overwiting previous contents). */
472 
473 		/* Temporarily drop our reference to the model so that as the model
474 		   pushes its current state to us, we don't try to update it. */
475 		boost::shared_ptr<MidiModel> mm = _model;
476 		_model.reset ();
477 
478 		/* Flush model contents to disk. */
479 		mm->sync_to_source (lm);
480 
481 		/* Reacquire model. */
482 		_model = mm;
483 
484 	} else {
485 		flush_midi(lm);
486 	}
487 }
488 
489 void
set_note_mode(const Lock & lock,NoteMode mode)490 MidiSource::set_note_mode(const Lock& lock, NoteMode mode)
491 {
492 	if (_model) {
493 		_model->set_note_mode(mode);
494 	}
495 }
496 
497 void
drop_model(const Lock & lock)498 MidiSource::drop_model (const Lock& lock)
499 {
500 	_model.reset();
501 	invalidate(lock);
502 	ModelChanged (); /* EMIT SIGNAL */
503 }
504 
505 void
set_model(const Lock & lock,boost::shared_ptr<MidiModel> m)506 MidiSource::set_model (const Lock& lock, boost::shared_ptr<MidiModel> m)
507 {
508 	_model = m;
509 	invalidate(lock);
510 	ModelChanged (); /* EMIT SIGNAL */
511 }
512 
513 Evoral::ControlList::InterpolationStyle
interpolation_of(Evoral::Parameter p) const514 MidiSource::interpolation_of (Evoral::Parameter p) const
515 {
516 	InterpolationStyleMap::const_iterator i = _interpolation_style.find (p);
517 	if (i == _interpolation_style.end()) {
518 		return EventTypeMap::instance().interpolation_of (p);
519 	}
520 
521 	return i->second;
522 }
523 
524 AutoState
automation_state_of(Evoral::Parameter p) const525 MidiSource::automation_state_of (Evoral::Parameter p) const
526 {
527 	AutomationStateMap::const_iterator i = _automation_state.find (p);
528 	if (i == _automation_state.end()) {
529 		/* default to `play', otherwise if MIDI is recorded /
530 		   imported with controllers etc. they are by default
531 		   not played back, which is a little surprising.
532 		*/
533 		return Play;
534 	}
535 
536 	return i->second;
537 }
538 
539 /** Set interpolation style to be used for a given parameter.  This change will be
540  *  propagated to anyone who needs to know.
541  */
542 void
set_interpolation_of(Evoral::Parameter p,Evoral::ControlList::InterpolationStyle s)543 MidiSource::set_interpolation_of (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
544 {
545 	if (interpolation_of (p) == s) {
546 		return;
547 	}
548 
549 	if (EventTypeMap::instance().interpolation_of (p) == s) {
550 		/* interpolation type is being set to the default, so we don't need a note in our map */
551 		_interpolation_style.erase (p);
552 	} else {
553 		_interpolation_style[p] = s;
554 	}
555 
556 	InterpolationChanged (p, s); /* EMIT SIGNAL */
557 }
558 
559 void
set_automation_state_of(Evoral::Parameter p,AutoState s)560 MidiSource::set_automation_state_of (Evoral::Parameter p, AutoState s)
561 {
562 	if (automation_state_of (p) == s) {
563 		return;
564 	}
565 
566 	if (s == Play) {
567 		/* automation state is being set to the default, so we don't need a note in our map */
568 		_automation_state.erase (p);
569 	} else {
570 		_automation_state[p] = s;
571 	}
572 
573 	AutomationStateChanged (p, s); /* EMIT SIGNAL */
574 }
575 
576 void
copy_interpolation_from(boost::shared_ptr<MidiSource> s)577 MidiSource::copy_interpolation_from (boost::shared_ptr<MidiSource> s)
578 {
579 	copy_interpolation_from (s.get ());
580 }
581 
582 void
copy_automation_state_from(boost::shared_ptr<MidiSource> s)583 MidiSource::copy_automation_state_from (boost::shared_ptr<MidiSource> s)
584 {
585 	copy_automation_state_from (s.get ());
586 }
587 
588 void
copy_interpolation_from(MidiSource * s)589 MidiSource::copy_interpolation_from (MidiSource* s)
590 {
591 	_interpolation_style = s->_interpolation_style;
592 
593 	/* XXX: should probably emit signals here */
594 }
595 
596 void
copy_automation_state_from(MidiSource * s)597 MidiSource::copy_automation_state_from (MidiSource* s)
598 {
599 	_automation_state = s->_automation_state;
600 
601 	/* XXX: should probably emit signals here */
602 }
603