use a note tracker to resolve notes cut off during render by the end of the region
[ardour.git] / libs / ardour / midi_track.cc
1 /*
2  * Copyright (C) 2006-2016 David Robillard <d@drobilla.net>
3  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
4  * Copyright (C) 2007-2019 Paul Davis <paul@linuxaudiosystems.com>
5  * Copyright (C) 2008-2012 Hans Baier <hansfbaier@googlemail.com>
6  * Copyright (C) 2013-2016 Tim Mayberry <mojofunk@gmail.com>
7  * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
8  * Copyright (C) 2013 John Emmas <john@creativepost.co.uk>
9  * Copyright (C) 2015-2018 Ben Loftis <ben@harrisonconsoles.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 #include <cmath>
26
27 #ifdef COMPILER_MSVC
28 #include <float.h>
29
30 // 'std::isinf()' and 'std::isnan()' are not available in MSVC.
31 #define isinf_local(val) !((bool)_finite((double)val))
32 #define isnan_local(val) (bool)_isnan((double)val)
33 #else
34 #define isinf_local std::isinf
35 #define isnan_local std::isnan
36 #endif
37
38 #include "pbd/enumwriter.h"
39 #include "pbd/types_convert.h"
40 #include "evoral/midi_util.h"
41
42 #include "ardour/amp.h"
43 #include "ardour/beats_samples_converter.h"
44 #include "ardour/buffer_set.h"
45 #include "ardour/debug.h"
46 #include "ardour/delivery.h"
47 #include "ardour/disk_reader.h"
48 #include "ardour/disk_writer.h"
49 #include "ardour/event_type_map.h"
50 #include "ardour/meter.h"
51 #include "ardour/midi_playlist.h"
52 #include "ardour/midi_port.h"
53 #include "ardour/midi_region.h"
54 #include "ardour/midi_track.h"
55 #include "ardour/monitor_control.h"
56 #include "ardour/parameter_types.h"
57 #include "ardour/port.h"
58 #include "ardour/processor.h"
59 #include "ardour/profile.h"
60 #include "ardour/route_group_specialized.h"
61 #include "ardour/session.h"
62 #include "ardour/session_playlists.h"
63 #include "ardour/types_convert.h"
64 #include "ardour/utils.h"
65
66 #include "pbd/i18n.h"
67
68 namespace ARDOUR {
69 class InterThreadInfo;
70 class MidiSource;
71 class Region;
72 class SMFSource;
73 }
74
75 using namespace std;
76 using namespace ARDOUR;
77 using namespace PBD;
78
79 MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
80         : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
81         , _immediate_events(6096) // FIXME: size?
82         , _immediate_event_buffer(6096)
83         , _step_edit_ring_buffer(64) // FIXME: size?
84         , _note_mode (Sustained)
85         , _step_editing (false)
86         , _input_active (true)
87 {
88         _session.SessionLoaded.connect_same_thread (*this, boost::bind (&MidiTrack::restore_controls, this));
89 }
90
91 MidiTrack::~MidiTrack ()
92 {
93 }
94
95 int
96 MidiTrack::init ()
97 {
98         if (Track::init ()) {
99                 return -1;
100         }
101
102         _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
103
104         _disk_writer->set_note_mode (_note_mode);
105         _disk_reader->reset_tracker ();
106
107         _disk_writer->DataRecorded.connect_same_thread (*this, boost::bind (&MidiTrack::data_recorded, this, _1));
108
109         return 0;
110 }
111
112 void
113 MidiTrack::data_recorded (boost::weak_ptr<MidiSource> src)
114 {
115         DataRecorded (src); /* EMIT SIGNAL */
116 }
117
118 bool
119 MidiTrack::can_be_record_safe ()
120 {
121         if (_step_editing) {
122                 return false;
123         }
124
125         return Track::can_be_record_safe ();
126 }
127
128 bool
129 MidiTrack::can_be_record_enabled ()
130 {
131         if (_step_editing) {
132                 return false;
133         }
134
135         return Track::can_be_record_enabled ();
136 }
137
138 int
139 MidiTrack::set_state (const XMLNode& node, int version)
140 {
141         /* This must happen before Track::set_state(), as there will be a buffer
142            fill during that call, and we must fill buffers using the correct
143            _note_mode.
144         */
145         if (!node.get_property (X_("note-mode"), _note_mode)) {
146                 _note_mode = Sustained;
147         }
148
149         if (Track::set_state (node, version)) {
150                 return -1;
151         }
152
153         // No destructive MIDI tracks (yet?)
154         _mode = Normal;
155
156         bool yn;
157         if (node.get_property ("input-active", yn)) {
158                 set_input_active (yn);
159         }
160
161         ChannelMode playback_channel_mode = AllChannels;
162         ChannelMode capture_channel_mode = AllChannels;
163
164         node.get_property ("playback-channel-mode", playback_channel_mode);
165         node.get_property ("capture-channel-mode", capture_channel_mode);
166
167         if (node.get_property ("channel-mode", playback_channel_mode)) {
168                 /* 3.0 behaviour where capture and playback modes were not separated */
169                 capture_channel_mode = playback_channel_mode;
170         }
171
172         XMLProperty const * prop;
173
174         unsigned int playback_channel_mask = 0xffff;
175         unsigned int capture_channel_mask = 0xffff;
176
177         if ((prop = node.property ("playback-channel-mask")) != 0) {
178                 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
179         }
180         if ((prop = node.property ("capture-channel-mask")) != 0) {
181                 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
182         }
183         if ((prop = node.property ("channel-mask")) != 0) {
184                 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
185                 capture_channel_mask = playback_channel_mask;
186         }
187
188         set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
189         set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
190
191         pending_state = const_cast<XMLNode*> (&node);
192
193         if (_session.loading ()) {
194                 _session.StateReady.connect_same_thread (
195                         *this, boost::bind (&MidiTrack::set_state_part_two, this));
196         } else {
197                 set_state_part_two ();
198         }
199
200         return 0;
201 }
202
203 XMLNode&
204 MidiTrack::state(bool save_template)
205 {
206         XMLNode& root (Track::state (save_template));
207         XMLNode* freeze_node;
208         char buf[64];
209
210         if (_freeze_record.playlist) {
211                 XMLNode* inode;
212
213                 freeze_node = new XMLNode (X_("freeze-info"));
214                 freeze_node->set_property ("playlist", _freeze_record.playlist->name());
215                 freeze_node->set_property ("state", _freeze_record.state);
216
217                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
218                         inode = new XMLNode (X_("processor"));
219                         inode->set_property (X_("id"), id());
220                         inode->add_child_copy ((*i)->state);
221
222                         freeze_node->add_child_nocopy (*inode);
223                 }
224
225                 root.add_child_nocopy (*freeze_node);
226         }
227
228         root.set_property("playback-channel-mode", get_playback_channel_mode());
229         root.set_property("capture-channel-mode", get_capture_channel_mode());
230         snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
231         root.set_property("playback-channel-mask", std::string(buf));
232         snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
233         root.set_property("capture-channel-mask", std::string(buf));
234
235         root.set_property ("note-mode", _note_mode);
236         root.set_property ("step-editing", _step_editing);
237         root.set_property ("input-active", _input_active);
238
239         for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
240                 if (boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) {
241                         boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c->second);
242                         assert (ac);
243                         root.add_child_nocopy (ac->get_state ());
244                 }
245         }
246
247         return root;
248 }
249
250 void
251 MidiTrack::set_state_part_two ()
252 {
253         XMLNode* fnode;
254
255         /* This is called after all session state has been restored but before
256            have been made ports and connections are established.
257         */
258
259         if (pending_state == 0) {
260                 return;
261         }
262
263         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
264
265                 _freeze_record.state = Frozen;
266
267                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
268                         delete *i;
269                 }
270                 _freeze_record.processor_info.clear ();
271
272                 std::string str;
273                 if (fnode->get_property (X_("playlist"), str)) {
274                         boost::shared_ptr<Playlist> pl = _session.playlists()->by_name (str);
275                         if (pl) {
276                                 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
277                         } else {
278                                 _freeze_record.playlist.reset();
279                                 _freeze_record.state = NoFreeze;
280                                 return;
281                         }
282                 }
283
284                 fnode->get_property (X_("state"), _freeze_record.state);
285
286                 XMLNodeConstIterator citer;
287                 XMLNodeList clist = fnode->children();
288
289                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
290                         if ((*citer)->name() != X_("processor")) {
291                                 continue;
292                         }
293
294                         if (!(*citer)->get_property (X_("id"), str)) {
295                                 continue;
296                         }
297
298                         FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
299                                                                                    boost::shared_ptr<Processor>());
300                         frii->id = str;
301                         _freeze_record.processor_info.push_back (frii);
302                 }
303         }
304
305         return;
306 }
307
308 void
309 MidiTrack::restore_controls ()
310 {
311         // TODO order events (CC before PGM to set banks)
312         for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
313                 boost::shared_ptr<MidiTrack::MidiControl> mctrl = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second);
314                 if (mctrl) {
315                         mctrl->restore_value();
316                 }
317         }
318 }
319
320 void
321 MidiTrack::update_controls (BufferSet const& bufs)
322 {
323         const MidiBuffer& buf = bufs.get_midi(0);
324         for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
325                 const Evoral::Event<samplepos_t>&         ev     = *e;
326                 const Evoral::Parameter                  param   = midi_parameter(ev.buffer(), ev.size());
327                 const boost::shared_ptr<AutomationControl> control = automation_control (param);
328                 if (control) {
329                         double old = control->get_double (false, 0);
330                         control->set_double (ev.value(), 0, false);
331                         if (old != ev.value()) {
332                                 control->Changed (false, Controllable::NoGroup);
333                         }
334                 }
335         }
336 }
337
338 int
339 MidiTrack::no_roll_unlocked (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool state_changing)
340 {
341         int ret = Track::no_roll_unlocked (nframes, start_sample, end_sample, state_changing);
342
343         if (ret == 0 && _step_editing) {
344                 push_midi_input_to_step_edit_ringbuffer (nframes);
345         }
346
347         return ret;
348 }
349
350 void
351 MidiTrack::realtime_locate ()
352 {
353         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
354
355         if (!lm.locked ()) {
356                 return;
357         }
358
359         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
360                 (*i)->realtime_locate ();
361         }
362
363         _disk_reader->resolve_tracker (_immediate_events, Port::port_offset());
364 }
365
366 void
367 MidiTrack::non_realtime_locate (samplepos_t pos)
368 {
369         Track::non_realtime_locate(pos);
370
371         boost::shared_ptr<MidiPlaylist> playlist = _disk_writer->midi_playlist();
372         if (!playlist) {
373                 return;
374         }
375
376         /* Get the top unmuted region at this position. */
377         boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(playlist->top_unmuted_region_at(pos));
378
379         if (!region) {
380                 return;
381         }
382
383         /* the source may be missing, but the control still referenced in the GUI */
384         if (!region->midi_source() || !region->model()) {
385                 return;
386         }
387
388         Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
389         if (!lm.locked()) {
390                 return;
391         }
392
393         /* Update track controllers based on its "automation". */
394         const samplepos_t     origin = region->position() - region->start();
395         BeatsSamplesConverter bfc(_session.tempo_map(), origin);
396
397         for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
398
399                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c->second);
400
401                 if (!ac->automation_playback()) {
402                         continue;
403                 }
404
405                 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
406                 boost::shared_ptr<Evoral::Control>        rcontrol;
407
408                 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
409
410                     (rcontrol = region->control(tcontrol->parameter()))) {
411                         const Temporal::Beats pos_beats = bfc.from(pos - origin);
412                         if (rcontrol->list()->size() > 0) {
413                                 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
414                         }
415                 }
416         }
417 }
418
419 void
420 MidiTrack::push_midi_input_to_step_edit_ringbuffer (samplecnt_t nframes)
421 {
422         PortSet& ports (_input->ports());
423
424         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
425
426                 Buffer& b (p->get_buffer (nframes));
427                 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
428                 assert (mb);
429
430                 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
431
432                         const Evoral::Event<samplepos_t> ev(*e, false);
433
434                         /* note on, since for step edit, note length is determined
435                            elsewhere
436                         */
437
438                         if (ev.is_note_on()) {
439                                 /* we don't care about the time for this purpose */
440                                 _step_edit_ring_buffer.write (0, ev.event_type(), ev.size(), ev.buffer());
441                         }
442                 }
443         }
444 }
445
446 void
447 MidiTrack::snapshot_out_of_band_data (samplecnt_t nframes)
448 {
449         _immediate_event_buffer.clear ();
450         if (0 == _immediate_events.read_space()) {
451                 return;
452         }
453
454         assert (nframes > 0);
455
456         DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
457                                 name(), _immediate_events.read_space()));
458
459         /* write as many of the immediate events as we can, but give "true" as
460          * the last argument ("stop on overflow in destination") so that we'll
461          * ship the rest out next time.
462          *
463          * the Port::port_offset() + (nframes-1) argument puts all these events at the last
464          * possible position of the output buffer, so that we do not
465          * violate monotonicity when writing. Port::port_offset() will
466          * be non-zero if we're in a split process cycle.
467          */
468         _immediate_events.read (_immediate_event_buffer, 0, 1, Port::port_offset() + nframes - 1, true);
469 }
470
471 void
472 MidiTrack::write_out_of_band_data (BufferSet& bufs, samplecnt_t nframes) const
473 {
474         MidiBuffer& buf (bufs.get_midi (0));
475         buf.merge_from (_immediate_event_buffer, nframes);
476 }
477
478 int
479 MidiTrack::export_stuff (BufferSet&                   buffers,
480                          samplepos_t                  start,
481                          samplecnt_t                  nframes,
482                          boost::shared_ptr<Processor> endpoint,
483                          bool                         include_endpoint,
484                          bool                         for_export,
485                          bool                         for_freeze)
486 {
487         if (buffers.count().n_midi() == 0) {
488                 return -1;
489         }
490
491         Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
492
493         boost::shared_ptr<MidiPlaylist> mpl = _disk_writer->midi_playlist();
494         if (!mpl) {
495                 return -2;
496         }
497         mpl->reset_note_trackers (); // TODO once at start and end ?
498
499         buffers.get_midi(0).clear();
500         if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
501                 return -1;
502         }
503
504         if (endpoint && !for_export) {
505                 MidiBuffer& buf = buffers.get_midi(0);
506                 for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
507                         MidiBuffer::TimeType *t = i.timeptr ();
508                         *t -= start;
509                 }
510                 bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
511         }
512         mpl->reset_note_trackers ();
513
514         return 0;
515 }
516
517 boost::shared_ptr<Region>
518 MidiTrack::bounce (InterThreadInfo& itt)
519 {
520         return bounce_range (_session.current_start_sample(), _session.current_end_sample(), itt, main_outs(), false);
521 }
522
523 boost::shared_ptr<Region>
524 MidiTrack::bounce_range (samplepos_t                  start,
525                          samplepos_t                  end,
526                          InterThreadInfo&             itt,
527                          boost::shared_ptr<Processor> endpoint,
528                          bool                         include_endpoint)
529 {
530         vector<boost::shared_ptr<Source> > srcs;
531         return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
532 }
533
534 void
535 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
536 {
537         std::cerr << "MIDI freeze currently unsupported" << std::endl;
538 }
539
540 void
541 MidiTrack::unfreeze ()
542 {
543         _freeze_record.state = UnFrozen;
544         FreezeChange (); /* EMIT SIGNAL */
545 }
546
547 void
548 MidiTrack::set_note_mode (NoteMode m)
549 {
550         _note_mode = m;
551         _disk_writer->set_note_mode(m);
552 }
553
554 std::string
555 MidiTrack::describe_parameter (Evoral::Parameter param)
556 {
557         const std::string str(instrument_info().get_controller_name(param));
558         return str.empty() ? Automatable::describe_parameter(param) : str;
559 }
560
561 void
562 MidiTrack::midi_panic()
563 {
564         DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
565         for (uint8_t channel = 0; channel <= 0xF; channel++) {
566                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
567                 write_immediate_event(3, ev);
568                 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
569                 write_immediate_event(3, ev);
570                 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
571                 write_immediate_event(3, ev);
572         }
573 }
574
575 /** \return true on success, false on failure (no buffer space left)
576  */
577 bool
578 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
579 {
580         if (!Evoral::midi_event_is_valid(buf, size)) {
581                 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
582                 return false;
583         }
584         return (_immediate_events.write (0, Evoral::MIDI_EVENT, size, buf) == size);
585 }
586
587 void
588 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
589 {
590         switch (param.type()) {
591         case MidiCCAutomation:
592         case MidiPgmChangeAutomation:
593         case MidiPitchBenderAutomation:
594         case MidiChannelPressureAutomation:
595         case MidiNotePressureAutomation:
596         case MidiSystemExclusiveAutomation:
597                 /* The track control for MIDI parameters is for immediate events to act
598                    as a control surface, write/touch for them is not currently
599                    supported. */
600                 return;
601         default:
602                 Automatable::set_parameter_automation_state(param, state);
603         }
604 }
605
606 void
607 MidiTrack::MidiControl::restore_value ()
608 {
609         actually_set_value (get_value(), Controllable::NoGroup);
610 }
611
612 void
613 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
614 {
615         const Evoral::Parameter &parameter = _list ? _list->parameter() : Control::parameter();
616         const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
617
618         bool valid = false;
619         if (isinf_local(val)) {
620                 cerr << "MIDIControl value is infinity" << endl;
621         } else if (isnan_local(val)) {
622                 cerr << "MIDIControl value is NaN" << endl;
623         } else if (val < desc.lower) {
624                 cerr << "MIDIControl value is < " << desc.lower << endl;
625         } else if (val > desc.upper) {
626                 cerr << "MIDIControl value is > " << desc.upper << endl;
627         } else {
628                 valid = true;
629         }
630
631         if (!valid) {
632                 return;
633         }
634
635         assert(val <= desc.upper);
636         if ( ! _list || ! automation_playback()) {
637                 size_t size = 3;
638                 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
639                 switch(parameter.type()) {
640                 case MidiCCAutomation:
641                         ev[0] |= MIDI_CMD_CONTROL;
642                         ev[1] = parameter.id();
643                         ev[2] = int(val);
644                         break;
645
646                 case MidiPgmChangeAutomation:
647                         size = 2;
648                         ev[0] |= MIDI_CMD_PGM_CHANGE;
649                         ev[1] = int(val);
650                         break;
651
652                 case MidiChannelPressureAutomation:
653                         size = 2;
654                         ev[0] |= MIDI_CMD_CHANNEL_PRESSURE;
655                         ev[1] = int(val);
656                         break;
657
658                 case MidiNotePressureAutomation:
659                         ev[0] |= MIDI_CMD_NOTE_PRESSURE;
660                         ev[1] = parameter.id();
661                         ev[2] = int(val);
662                         break;
663
664                 case MidiPitchBenderAutomation:
665                         ev[0] |= MIDI_CMD_BENDER;
666                         ev[1] = 0x7F & int(val);
667                         ev[2] = 0x7F & (int(val) >> 7);
668                         break;
669
670                 default:
671                         size = 0;
672                         assert(false);
673                 }
674                 _route->write_immediate_event(size,  ev);
675         }
676
677         AutomationControl::actually_set_value(val, group_override);
678 }
679
680 void
681 MidiTrack::set_step_editing (bool yn)
682 {
683         if (_session.record_status() != Session::Disabled) {
684                 return;
685         }
686
687         if (yn != _step_editing) {
688                 _step_editing = yn;
689                 StepEditStatusChange (yn);
690         }
691 }
692
693 boost::shared_ptr<SMFSource>
694 MidiTrack::write_source (uint32_t)
695 {
696         return _disk_writer->midi_write_source ();
697 }
698
699 void
700 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
701 {
702         if (_playback_filter.set_channel_mode(mode, mask)) {
703                 _session.set_dirty();
704         }
705 }
706
707 void
708 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
709 {
710         if (_capture_filter.set_channel_mode(mode, mask)) {
711                 _session.set_dirty();
712         }
713 }
714
715 void
716 MidiTrack::set_playback_channel_mask (uint16_t mask)
717 {
718         if (_playback_filter.set_channel_mask(mask)) {
719                 _session.set_dirty();
720         }
721 }
722
723 void
724 MidiTrack::set_capture_channel_mask (uint16_t mask)
725 {
726         if (_capture_filter.set_channel_mask(mask)) {
727                 _session.set_dirty();
728         }
729 }
730
731 boost::shared_ptr<MidiPlaylist>
732 MidiTrack::midi_playlist ()
733 {
734         return boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
735 }
736
737 bool
738 MidiTrack::input_active () const
739 {
740         return _input_active;
741 }
742
743 void
744 MidiTrack::set_input_active (bool yn)
745 {
746         if (yn != _input_active) {
747                 _input_active = yn;
748                 map_input_active (yn);
749                 InputActiveChanged (); /* EMIT SIGNAL */
750         }
751 }
752
753 void
754 MidiTrack::map_input_active (bool yn)
755 {
756         if (!_input) {
757                 return;
758         }
759
760         PortSet& ports (_input->ports());
761
762         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
763                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
764                 if (yn != mp->input_active()) {
765                         mp->set_input_active (yn);
766                 }
767         }
768 }
769
770 void
771 MidiTrack::track_input_active (IOChange change, void* /* src */)
772 {
773         if (change.type & IOChange::ConfigurationChanged) {
774                 map_input_active (_input_active);
775         }
776 }
777
778 boost::shared_ptr<MidiBuffer>
779 MidiTrack::get_gui_feed_buffer () const
780 {
781         return _disk_writer->get_gui_feed_buffer ();
782 }
783
784 void
785 MidiTrack::act_on_mute ()
786 {
787         /* this is called right after our mute status has changed.
788            if we are now muted, send suitable output to shutdown
789            all our notes.
790
791            XXX we should should also stop all relevant note trackers.
792         */
793
794         /* If we haven't got a diskstream yet, there's nothing to worry about,
795            and we can't call get_channel_mask() anyway.
796         */
797         if (!_disk_writer) {
798                 return;
799         }
800
801         if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
802                 /* only send messages for channels we are using */
803
804                 uint16_t mask = _playback_filter.get_channel_mask();
805
806                 for (uint8_t channel = 0; channel <= 0xF; channel++) {
807
808                         if ((1<<channel) & mask) {
809
810                                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
811                                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
812                                 write_immediate_event (3, ev);
813
814                                 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
815                                    silence notes that came from another non-muted track. */
816                         }
817                 }
818
819                 /* Resolve active notes. */
820                 _disk_reader->resolve_tracker(_immediate_events, Port::port_offset());
821         }
822 }
823
824 void
825 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
826 {
827         Track::monitoring_changed (self, gcd);
828
829         /* monitoring state changed, so flush out any on notes at the
830          * port level.
831          */
832
833         PortSet& ports (_output->ports());
834
835         for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
836                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
837                 if (mp) {
838                         mp->require_resolve ();
839                 }
840         }
841
842         _disk_reader->reset_tracker ();
843 }
844
845 MonitorState
846 MidiTrack::monitoring_state () const
847 {
848         MonitorState ms = Track::monitoring_state();
849         if (ms == MonitoringSilence) {
850                 return MonitoringInput;
851         }
852         return ms;
853 }
854
855 MonitorState
856 MidiTrack::get_auto_monitoring_state () const
857 {
858         //if we are a midi track,  we ignore auto_input, tape_mode, etc etc.  "Auto" will monitor Disk+In
859         return MonitoringCue;
860 }
861
862 void
863 MidiTrack::filter_input (BufferSet& bufs)
864 {
865         _capture_filter.filter (bufs);
866 }
867
868 void
869 MidiTrack::realtime_handle_transport_stopped ()
870 {
871         Route::realtime_handle_transport_stopped ();
872         _disk_reader->resolve_tracker (_immediate_events, Port::port_offset());
873 }
874
875 void
876 MidiTrack::playlist_contents_changed ()
877
878 {
879 }