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>
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.
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.
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.
35 #include <glibmm/fileutils.h>
36 #include <glibmm/miscutils.h>
38 #include "pbd/xml++.h"
39 #include "pbd/pthread_utils.h"
40 #include "pbd/basename.h"
42 #include "evoral/Control.hpp"
43 #include "evoral/EventSink.hpp"
45 #include "ardour/debug.h"
46 #include "ardour/file_source.h"
47 #include "ardour/midi_channel_filter.h"
48 #include "ardour/midi_cursor.h"
49 #include "ardour/midi_model.h"
50 #include "ardour/midi_source.h"
51 #include "ardour/midi_state_tracker.h"
52 #include "ardour/session.h"
53 #include "ardour/session_directory.h"
54 #include "ardour/source_factory.h"
55 #include "ardour/tempo.h"
59 namespace ARDOUR { template <typename T> class MidiRingBuffer; }
62 using namespace ARDOUR;
65 MidiSource::MidiSource (Session& s, string name, Source::Flag flags)
66 : Source(s, DataType::MIDI, name, flags)
70 , _capture_loop_length(0)
74 MidiSource::MidiSource (Session& s, const XMLNode& node)
79 , _capture_loop_length(0)
81 if (set_state (node, Stateful::loading_state_version)) {
82 throw failed_constructor();
86 MidiSource::~MidiSource ()
88 /* invalidate any existing iterators */
93 MidiSource::get_state ()
95 XMLNode& node (Source::get_state());
97 if (_captured_for.length()) {
98 node.set_property ("captured-for", _captured_for);
101 for (InterpolationStyleMap::const_iterator i = _interpolation_style.begin(); i != _interpolation_style.end(); ++i) {
102 XMLNode* child = node.add_child (X_("InterpolationStyle"));
103 child->set_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first));
104 child->set_property (X_("style"), enum_2_string (i->second));
107 for (AutomationStateMap::const_iterator i = _automation_state.begin(); i != _automation_state.end(); ++i) {
108 XMLNode* child = node.add_child (X_("AutomationState"));
109 child->set_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first));
110 child->set_property (X_("state"), enum_2_string (i->second));
117 MidiSource::set_state (const XMLNode& node, int /*version*/)
119 node.get_property ("captured-for", _captured_for);
122 XMLNodeList children = node.children ();
123 for (XMLNodeConstIterator i = children.begin(); i != children.end(); ++i) {
124 if ((*i)->name() == X_("InterpolationStyle")) {
125 if (!(*i)->get_property (X_("parameter"), str)) {
126 error << _("Missing parameter property on InterpolationStyle") << endmsg;
129 Evoral::Parameter p = EventTypeMap::instance().from_symbol (str);
132 case MidiCCAutomation:
133 case MidiPgmChangeAutomation: break;
134 case MidiChannelPressureAutomation: break;
135 case MidiNotePressureAutomation: break;
136 case MidiPitchBenderAutomation: break;
137 case MidiSystemExclusiveAutomation:
138 cerr << "Parameter \"" << str << "\" is system exclusive - no automation possible!\n";
141 cerr << "Parameter \"" << str << "\" found for MIDI source ... not legal; ignoring this parameter\n";
145 if (!(*i)->get_property (X_("style"), str)) {
146 error << _("Missing style property on InterpolationStyle") << endmsg;
149 Evoral::ControlList::InterpolationStyle s =
150 static_cast<Evoral::ControlList::InterpolationStyle>(string_2_enum (str, s));
151 set_interpolation_of (p, s);
153 } else if ((*i)->name() == X_("AutomationState")) {
154 if (!(*i)->get_property (X_("parameter"), str)) {
155 error << _("Missing parameter property on AutomationState") << endmsg;
158 Evoral::Parameter p = EventTypeMap::instance().from_symbol (str);
160 if (!(*i)->get_property (X_("state"), str)) {
161 error << _("Missing state property on AutomationState") << endmsg;
164 AutoState s = static_cast<AutoState>(string_2_enum (str, s));
165 set_automation_state_of (p, s);
173 MidiSource::empty () const
175 return !_length_beats;
179 MidiSource::length (samplepos_t pos) const
181 if (!_length_beats) {
185 BeatsSamplesConverter converter(_session.tempo_map(), pos);
186 return converter.to(_length_beats);
190 MidiSource::update_length (samplecnt_t)
192 // You're not the boss of me!
196 MidiSource::invalidate (const Lock& lock)
198 Invalidated(_session.transport_rolling());
202 MidiSource::midi_read (const Lock& lm,
203 Evoral::EventSink<samplepos_t>& dst,
204 samplepos_t source_start,
207 Evoral::Range<samplepos_t>* loop_range,
209 MidiStateTracker* tracker,
210 MidiChannelFilter* filter,
211 const std::set<Evoral::Parameter>& filtered,
212 const double pos_beats,
213 const double start_beats) const
215 BeatsSamplesConverter converter(_session.tempo_map(), source_start);
217 const double start_qn = pos_beats - start_beats;
219 DEBUG_TRACE (DEBUG::MidiSourceIO,
220 string_compose ("MidiSource::midi_read() %5 sstart %1 start %2 cnt %3 tracker %4\n",
221 source_start, start, cnt, tracker, name()));
224 return read_unlocked (lm, dst, source_start, start, cnt, loop_range, tracker, filter);
227 // Find appropriate model iterator
228 Evoral::Sequence<Temporal::Beats>::const_iterator& i = cursor.iter;
229 const bool linear_read = cursor.last_read_end != 0 && start == cursor.last_read_end;
230 if (!linear_read || !i.valid()) {
231 /* Cached iterator is invalid, search for the first event past start.
232 Note that multiple tracks can use a MidiSource simultaneously, so
233 all playback state must be in parameters (the cursor) and must not
234 be cached in the source of model itself.
235 See http://tracker.ardour.org/view.php?id=6541
237 cursor.connect(Invalidated);
238 cursor.iter = _model->begin(converter.from(start), false, filtered, &cursor.active_notes);
239 cursor.active_notes.clear();
242 cursor.last_read_end = start + cnt;
244 // Copy events in [start, start + cnt) into dst
245 for (; i != _model->end(); ++i) {
247 // Offset by source start to convert event time to session time
249 samplepos_t time_samples = _session.tempo_map().sample_at_quarter_note (i->time().to_double() + start_qn);
251 if (time_samples < start + source_start) {
252 /* event too early */
256 } else if (time_samples >= start + cnt + source_start) {
258 DEBUG_TRACE (DEBUG::MidiSourceIO,
259 string_compose ("%1: reached end with event @ %2 vs. %3\n",
260 _name, time_samples, start+cnt));
268 time_samples = loop_range->squish (time_samples);
271 const uint8_t status = i->buffer()[0];
272 const bool is_channel_event = (0x80 <= (status & 0xF0)) && (status <= 0xE0);
273 if (filter && is_channel_event) {
274 /* Copy event so the filter can modify the channel. I'm not
275 sure if this is necessary here (channels are mapped later in
276 buffers anyway), but it preserves existing behaviour without
277 destroying events in the model during read. */
278 Evoral::Event<Temporal::Beats> ev(*i, true);
279 if (!filter->filter(ev.buffer(), ev.size())) {
280 dst.write(time_samples, ev.event_type(), ev.size(), ev.buffer());
282 DEBUG_TRACE (DEBUG::MidiSourceIO,
283 string_compose ("%1: filter event @ %2 type %3 size %4\n",
284 _name, time_samples, i->event_type(), i->size()));
287 dst.write (time_samples, i->event_type(), i->size(), i->buffer());
291 if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) {
293 DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 sz %3 within %4 .. %5 ",
294 _name, time_samples, i->size(),
295 start + source_start, start + cnt + source_start));
296 for (size_t n=0; n < i->size(); ++n) {
297 DEBUG_STR_APPEND(a,hex);
298 DEBUG_STR_APPEND(a,"0x");
299 DEBUG_STR_APPEND(a,(int)i->buffer()[n]);
300 DEBUG_STR_APPEND(a,' ');
302 DEBUG_STR_APPEND(a,'\n');
303 DEBUG_TRACE (DEBUG::MidiSourceIO, DEBUG_STR(a).str());
317 MidiSource::midi_write (const Lock& lm,
318 MidiRingBuffer<samplepos_t>& source,
319 samplepos_t source_start,
322 const samplecnt_t ret = write_unlocked (lm, source, source_start, cnt);
324 if (cnt == max_samplecnt) {
327 _capture_length += cnt;
334 MidiSource::mark_streaming_midi_write_started (const Lock& lock, NoteMode mode)
337 _model->set_note_mode (mode);
338 _model->start_write ();
345 MidiSource::mark_write_starting_now (samplecnt_t position,
346 samplecnt_t capture_length,
347 samplecnt_t loop_length)
349 /* I'm not sure if this is the best way to approach this, but
350 _capture_length needs to be set up with the transport sample
351 when a record actually starts, as it is used by
352 SMFSource::write_unlocked to decide whether incoming notes
353 are within the correct time range.
354 mark_streaming_midi_write_started (perhaps a more logical
355 place to do this) is not called at exactly the time when
356 record starts, and I don't think it necessarily can be
357 because it is not RT-safe.
360 set_natural_position (position);
361 _capture_length = capture_length;
362 _capture_loop_length = loop_length;
364 TempoMap& map (_session.tempo_map());
365 BeatsSamplesConverter converter(map, position);
366 _length_beats = converter.from(capture_length);
370 MidiSource::mark_streaming_write_started (const Lock& lock)
372 NoteMode note_mode = _model ? _model->note_mode() : Sustained;
373 mark_streaming_midi_write_started (lock, note_mode);
377 MidiSource::mark_midi_streaming_write_completed (const Lock& lock,
378 Evoral::Sequence<Temporal::Beats>::StuckNoteOption option,
382 _model->end_write (option, end);
384 /* Make captured controls discrete to play back user input exactly. */
385 for (MidiModel::Controls::iterator i = _model->controls().begin(); i != _model->controls().end(); ++i) {
386 if (i->second->list()) {
387 i->second->list()->set_interpolation(Evoral::ControlList::Discrete);
388 _interpolation_style.insert(std::make_pair(i->second->parameter(), Evoral::ControlList::Discrete));
398 MidiSource::mark_streaming_write_completed (const Lock& lock)
400 mark_midi_streaming_write_completed (lock, Evoral::Sequence<Temporal::Beats>::DeleteStuckNotes);
404 MidiSource::export_write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Temporal::Beats begin, Temporal::Beats end)
406 Lock newsrc_lock (newsrc->mutex ());
409 error << string_compose (_("programming error: %1"), X_("no model for MidiSource during export"));
413 _model->write_section_to (newsrc, newsrc_lock, begin, end, true);
415 newsrc->flush_midi(newsrc_lock);
421 MidiSource::write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Temporal::Beats begin, Temporal::Beats end)
423 Lock newsrc_lock (newsrc->mutex ());
425 newsrc->set_natural_position (_natural_position);
426 newsrc->copy_interpolation_from (this);
427 newsrc->copy_automation_state_from (this);
430 if (begin == Temporal::Beats() && end == std::numeric_limits<Temporal::Beats>::max()) {
431 _model->write_to (newsrc, newsrc_lock);
433 _model->write_section_to (newsrc, newsrc_lock, begin, end);
436 error << string_compose (_("programming error: %1"), X_("no model for MidiSource during ::clone()"));
440 newsrc->flush_midi(newsrc_lock);
442 /* force a reload of the model if the range is partial */
444 if (begin != Temporal::Beats() || end != std::numeric_limits<Temporal::Beats>::max()) {
445 newsrc->load_model (newsrc_lock, true);
447 newsrc->set_model (newsrc_lock, _model);
450 /* this file is not removable (but since it is MIDI, it is mutable) */
452 boost::dynamic_pointer_cast<FileSource> (newsrc)->prevent_deletion ();
458 MidiSource::session_saved()
462 /* this writes a copy of the data to disk.
463 XXX do we need to do this every time?
466 if (_model && _model->edited()) {
467 /* The model is edited, write its contents into the current source
468 file (overwiting previous contents). */
470 /* Temporarily drop our reference to the model so that as the model
471 pushes its current state to us, we don't try to update it. */
472 boost::shared_ptr<MidiModel> mm = _model;
475 /* Flush model contents to disk. */
476 mm->sync_to_source (lm);
478 /* Reacquire model. */
487 MidiSource::set_note_mode(const Lock& lock, NoteMode mode)
490 _model->set_note_mode(mode);
495 MidiSource::drop_model (const Lock& lock)
499 ModelChanged (); /* EMIT SIGNAL */
503 MidiSource::set_model (const Lock& lock, boost::shared_ptr<MidiModel> m)
507 ModelChanged (); /* EMIT SIGNAL */
510 Evoral::ControlList::InterpolationStyle
511 MidiSource::interpolation_of (Evoral::Parameter p) const
513 InterpolationStyleMap::const_iterator i = _interpolation_style.find (p);
514 if (i == _interpolation_style.end()) {
515 return EventTypeMap::instance().interpolation_of (p);
522 MidiSource::automation_state_of (Evoral::Parameter p) const
524 AutomationStateMap::const_iterator i = _automation_state.find (p);
525 if (i == _automation_state.end()) {
526 /* default to `play', otherwise if MIDI is recorded /
527 imported with controllers etc. they are by default
528 not played back, which is a little surprising.
536 /** Set interpolation style to be used for a given parameter. This change will be
537 * propagated to anyone who needs to know.
540 MidiSource::set_interpolation_of (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
542 if (interpolation_of (p) == s) {
546 if (EventTypeMap::instance().interpolation_of (p) == s) {
547 /* interpolation type is being set to the default, so we don't need a note in our map */
548 _interpolation_style.erase (p);
550 _interpolation_style[p] = s;
553 InterpolationChanged (p, s); /* EMIT SIGNAL */
557 MidiSource::set_automation_state_of (Evoral::Parameter p, AutoState s)
559 if (automation_state_of (p) == s) {
564 /* automation state is being set to the default, so we don't need a note in our map */
565 _automation_state.erase (p);
567 _automation_state[p] = s;
570 AutomationStateChanged (p, s); /* EMIT SIGNAL */
574 MidiSource::copy_interpolation_from (boost::shared_ptr<MidiSource> s)
576 copy_interpolation_from (s.get ());
580 MidiSource::copy_automation_state_from (boost::shared_ptr<MidiSource> s)
582 copy_automation_state_from (s.get ());
586 MidiSource::copy_interpolation_from (MidiSource* s)
588 _interpolation_style = s->_interpolation_style;
590 /* XXX: should probably emit signals here */
594 MidiSource::copy_automation_state_from (MidiSource* s)
596 _automation_state = s->_automation_state;
598 /* XXX: should probably emit signals here */