prevent MIDI tracks from ever being in MonitoringSilence state, allows use of piano...
[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
20 #include "pbd/enumwriter.h"
21 #include "pbd/convert.h"
22 #include "evoral/midi_util.h"
23
24 #include "ardour/buffer_set.h"
25 #include "ardour/debug.h"
26 #include "ardour/delivery.h"
27 #include "ardour/meter.h"
28 #include "ardour/midi_diskstream.h"
29 #include "ardour/midi_playlist.h"
30 #include "ardour/midi_port.h"
31 #include "ardour/midi_track.h"
32 #include "ardour/port.h"
33 #include "ardour/processor.h"
34 #include "ardour/session.h"
35 #include "ardour/session_playlists.h"
36 #include "ardour/utils.h"
37
38 #include "i18n.h"
39
40 namespace ARDOUR {
41 class InterThreadInfo;
42 class MidiSource;
43 class Region;
44 class SMFSource;
45 }
46
47 using namespace std;
48 using namespace ARDOUR;
49 using namespace PBD;
50
51 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
52         : Track (sess, name, flag, mode, DataType::MIDI)
53         , _immediate_events(1024) // FIXME: size?
54         , _step_edit_ring_buffer(64) // FIXME: size?
55         , _note_mode(Sustained)
56         , _step_editing (false)
57         , _input_active (true)
58 {
59 }
60
61 MidiTrack::~MidiTrack ()
62 {
63 }
64
65 int
66 MidiTrack::init ()
67 {
68         if (Track::init ()) {
69                 return -1;
70         }
71
72         _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
73
74         return 0;
75 }
76
77 boost::shared_ptr<Diskstream>
78 MidiTrack::create_diskstream ()
79 {
80         MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
81
82         if (_flags & Hidden) {
83                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
84         } else {
85                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
86         }
87
88         assert(_mode != Destructive);
89
90         return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
91 }
92
93
94 void
95 MidiTrack::set_record_enabled (bool yn, void *src)
96 {
97         if (_step_editing) {
98                 return;
99         }
100
101         Track::set_record_enabled (yn, src);
102 }
103
104 void
105 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
106 {
107         /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
108            and the diskstream must be set up to fill its buffers using the correct _note_mode.
109         */
110         boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
111         mds->set_note_mode (_note_mode);
112         
113         Track::set_diskstream (ds);
114
115         mds->reset_tracker ();  
116
117         _diskstream->set_track (this);
118         _diskstream->set_destructive (_mode == Destructive);
119         _diskstream->set_record_enabled (false);
120
121         _diskstream_data_recorded_connection.disconnect ();
122         mds->DataRecorded.connect_same_thread (
123                 _diskstream_data_recorded_connection,
124                 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
125
126         DiskstreamChanged (); /* EMIT SIGNAL */
127 }
128
129 boost::shared_ptr<MidiDiskstream>
130 MidiTrack::midi_diskstream() const
131 {
132         return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
133 }
134
135 int
136 MidiTrack::set_state (const XMLNode& node, int version)
137 {
138         const XMLProperty *prop;
139
140         /* This must happen before Track::set_state(), as there will be a buffer
141            fill during that call, and we must fill buffers using the correct
142            _note_mode.
143         */
144         if ((prop = node.property (X_("note-mode"))) != 0) {
145                 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
146         } else {
147                 _note_mode = Sustained;
148         }
149
150         if (Track::set_state (node, version)) {
151                 return -1;
152         }
153
154         // No destructive MIDI tracks (yet?)
155         _mode = Normal;
156
157         if ((prop = node.property ("input-active")) != 0) {
158                 set_input_active (string_is_affirmative (prop->value()));
159         }
160
161         pending_state = const_cast<XMLNode*> (&node);
162
163         if (_session.state_of_the_state() & Session::Loading) {
164                 _session.StateReady.connect_same_thread (
165                         *this, boost::bind (&MidiTrack::set_state_part_two, this));
166         } else {
167                 set_state_part_two ();
168         }
169
170         return 0;
171 }
172
173 XMLNode&
174 MidiTrack::state(bool full_state)
175 {
176         XMLNode& root (Track::state(full_state));
177         XMLNode* freeze_node;
178         char buf[64];
179
180         if (_freeze_record.playlist) {
181                 XMLNode* inode;
182
183                 freeze_node = new XMLNode (X_("freeze-info"));
184                 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
185                 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
186
187                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
188                         inode = new XMLNode (X_("processor"));
189                         (*i)->id.print (buf, sizeof(buf));
190                         inode->add_property (X_("id"), buf);
191                         inode->add_child_copy ((*i)->state);
192
193                         freeze_node->add_child_nocopy (*inode);
194                 }
195
196                 root.add_child_nocopy (*freeze_node);
197         }
198
199         root.add_property ("note-mode", enum_2_string (_note_mode));
200         root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
201         root.add_property ("input-active", (_input_active ? "yes" : "no"));
202
203         return root;
204 }
205
206 void
207 MidiTrack::set_state_part_two ()
208 {
209         XMLNode* fnode;
210         XMLProperty* prop;
211         LocaleGuard lg (X_("POSIX"));
212
213         /* This is called after all session state has been restored but before
214            have been made ports and connections are established.
215         */
216
217         if (pending_state == 0) {
218                 return;
219         }
220
221         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
222
223                 _freeze_record.state = Frozen;
224
225                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
226                         delete *i;
227                 }
228                 _freeze_record.processor_info.clear ();
229
230                 if ((prop = fnode->property (X_("playlist"))) != 0) {
231                         boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
232                         if (pl) {
233                                 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
234                         } else {
235                                 _freeze_record.playlist.reset();
236                                 _freeze_record.state = NoFreeze;
237                         return;
238                         }
239                 }
240
241                 if ((prop = fnode->property (X_("state"))) != 0) {
242                         _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
243                 }
244
245                 XMLNodeConstIterator citer;
246                 XMLNodeList clist = fnode->children();
247
248                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
249                         if ((*citer)->name() != X_("processor")) {
250                                 continue;
251                         }
252
253                         if ((prop = (*citer)->property (X_("id"))) == 0) {
254                                 continue;
255                         }
256
257                         FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
258                                                                                    boost::shared_ptr<Processor>());
259                         frii->id = prop->value ();
260                         _freeze_record.processor_info.push_back (frii);
261                 }
262         }
263
264         if (midi_diskstream ()) {
265                 midi_diskstream()->set_block_size (_session.get_block_size ());
266         }
267
268         return;
269 }
270
271 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
272  *  or set to false.
273  */
274 int
275 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
276 {
277         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
278         if (!lm.locked()) {
279                 return 0;
280         }
281
282         boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
283
284         if (n_outputs().n_total() == 0 && _processors.empty()) {
285                 return 0;
286         }
287
288         if (!_active) {
289                 silence (nframes);
290                 return 0;
291         }
292
293         framepos_t transport_frame = _session.transport_frame();
294
295         int dret;
296         framecnt_t playback_distance;
297
298         if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
299                 /* need to do this so that the diskstream sets its
300                    playback distance to zero, thus causing diskstream::commit
301                    to do nothing.
302                    */
303                 dret = diskstream->process (transport_frame, 0, playback_distance);
304                 need_butler = diskstream->commit (playback_distance);
305                 return dret;
306         }
307
308
309         _silent = false;
310
311         if ((dret = diskstream->process (transport_frame, nframes, playback_distance)) != 0) {
312                 need_butler = diskstream->commit (playback_distance);
313                 silence (nframes);
314                 return dret;
315         }
316
317         /* special condition applies */
318
319         if (_meter_point == MeterInput) {
320                 _input->process_input (_meter, start_frame, end_frame, nframes);
321         }
322
323         if (monitoring_state() == MonitoringInput) {
324
325                 /* not actually recording, but we want to hear the input material anyway,
326                    at least potentially (depending on monitoring options)
327                 */
328
329                 /* because the playback buffer is event based and not a
330                  * continuous stream, we need to make sure that we empty
331                  * it of events every cycle to avoid it filling up with events
332                  * read from disk, while we are actually monitoring input
333                  */
334
335                 diskstream->flush_playback (start_frame, end_frame);
336
337                 passthru (start_frame, end_frame, nframes, 0);
338
339         } else {
340
341                 /*
342                    XXX is it true that the earlier test on n_outputs()
343                    means that we can avoid checking it again here? i think
344                    so, because changing the i/o configuration of an IO
345                    requires holding the AudioEngine lock, which we hold
346                    while in the process() tree.
347                    */
348
349
350                 /* copy the diskstream data to all output buffers */
351
352                 BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
353                 MidiBuffer& mbuf (bufs.get_midi (0));
354
355                 /* we are a MIDI track, so we always start the chain with a
356                  * single-MIDI-channel diskstream 
357                  */
358                 ChanCount c;
359                 c.set_audio (0);
360                 c.set_midi (1);
361                 bufs.set_count (c);
362
363                 diskstream->get_playback (mbuf, nframes);
364
365                 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
366
367                 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
368
369                 /* final argument: don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
370
371                 process_output_buffers (
372                         bufs, start_frame, end_frame, nframes,
373                         declick, (!diskstream->record_enabled() && !_session.transport_stopped())
374                         );
375         }
376
377         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
378                 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
379                 if (d) {
380                         d->flush_buffers (nframes);
381                 }
382         }
383
384         need_butler = diskstream->commit (playback_distance);
385         
386         return 0;
387 }
388
389 int
390 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
391 {
392         int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
393
394         if (ret == 0 && _step_editing) {
395                 push_midi_input_to_step_edit_ringbuffer (nframes);
396         }
397
398         return ret;
399 }
400
401 void
402 MidiTrack::realtime_locate ()
403 {
404         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
405
406         if (!lm.locked ()) {
407                 return;
408         }
409
410         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
411                 (*i)->realtime_locate ();
412         }
413
414         midi_diskstream()->reset_tracker ();
415 }
416
417 void
418 MidiTrack::realtime_handle_transport_stopped ()
419 {
420         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
421
422         if (!lm.locked ()) {
423                 return;
424         }
425
426         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
427                 (*i)->realtime_handle_transport_stopped ();
428         }
429 }
430
431 void
432 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
433 {
434         PortSet& ports (_input->ports());
435
436         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
437
438                 Buffer& b (p->get_buffer (nframes));
439                 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
440                 assert (mb);
441
442                 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
443
444                         const Evoral::MIDIEvent<framepos_t> ev(*e, false);
445
446                         /* note on, since for step edit, note length is determined
447                            elsewhere
448                         */
449
450                         if (ev.is_note_on()) {
451                                 /* we don't care about the time for this purpose */
452                                 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
453                         }
454                 }
455         }
456 }
457
458 void
459 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
460 {
461         MidiBuffer& buf (bufs.get_midi (0));
462
463         // Append immediate events
464
465         if (_immediate_events.read_space()) {
466
467                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
468                                                             name(), _immediate_events.read_space()));
469
470                 /* write as many of the immediate events as we can, but give "true" as
471                  * the last argument ("stop on overflow in destination") so that we'll
472                  * ship the rest out next time.
473                  *
474                  * the (nframes-1) argument puts all these events at the last
475                  * possible position of the output buffer, so that we do not
476                  * violate monotonicity when writing.
477                  */
478
479                 _immediate_events.read (buf, 0, 1, nframes-1, true);
480         }
481 }
482
483 int
484 MidiTrack::export_stuff (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framecnt_t /*nframes*/, 
485                          boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/, bool /*forexport*/)
486 {
487         return -1;
488 }
489
490 boost::shared_ptr<Region>
491 MidiTrack::bounce (InterThreadInfo& /*itt*/)
492 {
493         std::cerr << "MIDI bounce currently unsupported" << std::endl;
494         return boost::shared_ptr<Region> ();
495 }
496
497
498 boost::shared_ptr<Region>
499 MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/,
500                          boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/)
501 {
502         std::cerr << "MIDI bounce range currently unsupported" << std::endl;
503         return boost::shared_ptr<Region> ();
504 }
505
506 void
507 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
508 {
509         std::cerr << "MIDI freeze currently unsupported" << std::endl;
510 }
511
512 void
513 MidiTrack::unfreeze ()
514 {
515         _freeze_record.state = UnFrozen;
516         FreezeChange (); /* EMIT SIGNAL */
517 }
518
519 void
520 MidiTrack::set_note_mode (NoteMode m)
521 {
522         _note_mode = m;
523         midi_diskstream()->set_note_mode(m);
524 }
525
526 void
527 MidiTrack::midi_panic()
528 {
529         DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
530         for (uint8_t channel = 0; channel <= 0xF; channel++) {
531                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
532                 write_immediate_event(3, ev);
533                 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
534                 write_immediate_event(3, ev);
535                 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
536                 write_immediate_event(3, ev);
537         }
538 }
539
540 /** \return true on success, false on failure (no buffer space left)
541  */
542 bool
543 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
544 {
545         if (!Evoral::midi_event_is_valid(buf, size)) {
546                 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
547                 return false;
548         }
549         const uint32_t type = EventTypeMap::instance().midi_event_type(buf[0]);
550         return (_immediate_events.write(0, type, size, buf) == size);
551 }
552
553 void
554 MidiTrack::MidiControl::set_value(double val)
555 {
556         bool valid = false;
557         if (std::isinf(val)) {
558                 cerr << "MIDIControl value is infinity" << endl;
559         } else if (std::isnan(val)) {
560                 cerr << "MIDIControl value is NaN" << endl;
561         } else if (val < _list->parameter().min()) {
562                 cerr << "MIDIControl value is < " << _list->parameter().min() << endl;
563         } else if (val > _list->parameter().max()) {
564                 cerr << "MIDIControl value is > " << _list->parameter().max() << endl;
565         } else {
566                 valid = true;
567         }
568
569         if (!valid) {
570                 return;
571         }
572
573         assert(val <= _list->parameter().max());
574         if ( ! automation_playback()) {
575                 size_t size = 3;
576                 uint8_t ev[3] = { _list->parameter().channel(), uint8_t (val), 0 };
577                 switch(_list->parameter().type()) {
578                 case MidiCCAutomation:
579                         ev[0] += MIDI_CMD_CONTROL;
580                         ev[1] = _list->parameter().id();
581                         ev[2] = int(val);
582                         break;
583
584                 case MidiPgmChangeAutomation:
585                         size = 2;
586                         ev[0] += MIDI_CMD_PGM_CHANGE;
587                         ev[1] = int(val);
588                         break;
589
590                 case MidiChannelPressureAutomation:
591                         size = 2;
592                         ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
593                         ev[1] = int(val);
594                         break;
595
596                 case MidiPitchBenderAutomation:
597                         ev[0] += MIDI_CMD_BENDER;
598                         ev[1] = 0x7F & int(val);
599                         ev[2] = 0x7F & (int(val) >> 7);
600                         break;
601
602                 default:
603                         assert(false);
604                 }
605                 _route->write_immediate_event(size,  ev);
606         }
607
608         AutomationControl::set_value(val);
609 }
610
611 void
612 MidiTrack::set_step_editing (bool yn)
613 {
614         if (_session.record_status() != Session::Disabled) {
615                 return;
616         }
617
618         if (yn != _step_editing) {
619                 _step_editing = yn;
620                 StepEditStatusChange (yn);
621         }
622 }
623
624 boost::shared_ptr<SMFSource>
625 MidiTrack::write_source (uint32_t)
626 {
627         return midi_diskstream()->write_source ();
628 }
629
630 void
631 MidiTrack::set_channel_mode (ChannelMode mode, uint16_t mask)
632 {
633         midi_diskstream()->set_channel_mode (mode, mask);
634 }
635
636 ChannelMode
637 MidiTrack::get_channel_mode ()
638 {
639         return midi_diskstream()->get_channel_mode ();
640 }
641
642 uint16_t
643 MidiTrack::get_channel_mask ()
644 {
645         return midi_diskstream()->get_channel_mask ();
646 }
647
648 boost::shared_ptr<MidiPlaylist>
649 MidiTrack::midi_playlist ()
650 {
651         return midi_diskstream()->midi_playlist ();
652 }
653
654 void
655 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
656 {
657         DataRecorded (src); /* EMIT SIGNAL */
658 }
659
660 bool
661 MidiTrack::input_active () const
662 {
663         return _input_active;
664 }
665
666 void
667 MidiTrack::set_input_active (bool yn)
668 {
669         if (yn != _input_active) {
670                 _input_active = yn;
671                 map_input_active (yn);
672                 InputActiveChanged (); /* EMIT SIGNAL */
673         }
674 }
675
676 void
677 MidiTrack::map_input_active (bool yn)
678 {
679         if (!_input) {
680                 return;
681         }
682
683         PortSet& ports (_input->ports());
684
685         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
686                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
687                 if (yn != mp->input_active()) {
688                         mp->set_input_active (yn);
689                 }
690         }
691 }
692
693 void
694 MidiTrack::track_input_active (IOChange change, void* /* src */)
695 {
696         if (change.type & IOChange::ConfigurationChanged) {
697                 map_input_active (_input_active);
698         }
699 }
700
701 boost::shared_ptr<Diskstream>
702 MidiTrack::diskstream_factory (XMLNode const & node)
703 {
704         return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
705 }
706
707 boost::shared_ptr<MidiBuffer>
708 MidiTrack::get_gui_feed_buffer () const
709 {
710         return midi_diskstream()->get_gui_feed_buffer ();
711 }
712
713 void
714 MidiTrack::act_on_mute ()
715 {
716         /* this is called right after our mute status has changed.
717            if we are now muted, send suitable output to shutdown
718            all our notes.
719
720            XXX we should should also stop all relevant note trackers.
721         */
722
723         /* If we haven't got a diskstream yet, there's nothing to worry about,
724            and we can't call get_channel_mask() anyway.
725         */
726         if (!midi_diskstream()) {
727                 return;
728         }
729
730         if (muted()) {
731                 /* only send messages for channels we are using */
732
733                 uint16_t mask = get_channel_mask();
734
735                 for (uint8_t channel = 0; channel <= 0xF; channel++) {
736
737                         if ((1<<channel) & mask) {
738
739                                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
740                                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
741                                 write_immediate_event (3, ev);
742                                 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
743                                 write_immediate_event (3, ev);
744                         }
745                 }
746         }
747 }
748         
749 void
750 MidiTrack::set_monitoring (MonitorChoice mc)
751 {
752         if (mc != _monitoring) {
753
754                 Track::set_monitoring (mc);
755                 
756                 /* monitoring state changed, so flush out any on notes at the
757                  * port level.
758                  */
759
760                 PortSet& ports (_output->ports());
761                 
762                 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
763                         boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
764                         if (mp) {
765                                 mp->require_resolve ();
766                         }
767                 }
768
769                 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
770                 
771                 if (md) {
772                         md->reset_tracker ();
773                 }
774         }
775 }
776
777 MonitorState
778 MidiTrack::monitoring_state () const
779 {
780         MonitorState ms = Track::monitoring_state();
781         if (ms == MonitoringSilence) {
782                 return MonitoringInput;
783         } 
784         return ms;
785 }