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