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