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