1d352d622bcd5dbaa78f382cb3bb5c676f634770
[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 (X_("note-mode"), enum_2_string (_note_mode));
200
201         root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
202         root.add_property ("note-mode", enum_2_string (_note_mode));
203         root.add_property ("input-active", (_input_active ? "yes" : "no"));
204
205         return root;
206 }
207
208 void
209 MidiTrack::set_state_part_two ()
210 {
211         XMLNode* fnode;
212         XMLProperty* prop;
213         LocaleGuard lg (X_("POSIX"));
214
215         /* This is called after all session state has been restored but before
216            have been made ports and connections are established.
217         */
218
219         if (pending_state == 0) {
220                 return;
221         }
222
223         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
224
225                 _freeze_record.state = Frozen;
226
227                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
228                         delete *i;
229                 }
230                 _freeze_record.processor_info.clear ();
231
232                 if ((prop = fnode->property (X_("playlist"))) != 0) {
233                         boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
234                         if (pl) {
235                                 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
236                         } else {
237                                 _freeze_record.playlist.reset();
238                                 _freeze_record.state = NoFreeze;
239                         return;
240                         }
241                 }
242
243                 if ((prop = fnode->property (X_("state"))) != 0) {
244                         _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
245                 }
246
247                 XMLNodeConstIterator citer;
248                 XMLNodeList clist = fnode->children();
249
250                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
251                         if ((*citer)->name() != X_("processor")) {
252                                 continue;
253                         }
254
255                         if ((prop = (*citer)->property (X_("id"))) == 0) {
256                                 continue;
257                         }
258
259                         FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
260                                                                                    boost::shared_ptr<Processor>());
261                         frii->id = prop->value ();
262                         _freeze_record.processor_info.push_back (frii);
263                 }
264         }
265
266         if (midi_diskstream ()) {
267                 midi_diskstream()->set_block_size (_session.get_block_size ());
268         }
269
270         return;
271 }
272
273 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
274  *  or set to false.
275  */
276 int
277 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
278 {
279         Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
280         if (!lm.locked()) {
281                 return 0;
282         }
283
284         boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
285
286         automation_snapshot (start_frame);
287
288         if (n_outputs().n_total() == 0 && _processors.empty()) {
289                 return 0;
290         }
291
292         if (!_active) {
293                 silence (nframes);
294                 return 0;
295         }
296
297         framepos_t transport_frame = _session.transport_frame();
298
299         int dret;
300         framecnt_t playback_distance;
301
302         if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
303                 /* need to do this so that the diskstream sets its
304                    playback distance to zero, thus causing diskstream::commit
305                    to do nothing.
306                    */
307                 dret = diskstream->process (transport_frame, 0, playback_distance);
308                 need_butler = diskstream->commit (playback_distance);
309                 return dret;
310         }
311
312
313         _silent = false;
314
315         if ((dret = diskstream->process (transport_frame, nframes, playback_distance)) != 0) {
316                 need_butler = diskstream->commit (playback_distance);
317                 silence (nframes);
318                 return dret;
319         }
320
321         /* special condition applies */
322
323         if (_meter_point == MeterInput) {
324                 _input->process_input (_meter, start_frame, end_frame, nframes);
325         }
326
327         if (monitoring_state() == MonitoringInput) {
328
329                 /* not actually recording, but we want to hear the input material anyway,
330                    at least potentially (depending on monitoring options)
331                 */
332
333                 /* because the playback buffer is event based and not a
334                  * continuous stream, we need to make sure that we empty
335                  * it of events every cycle to avoid it filling up with events
336                  * read from disk, while we are actually monitoring input
337                  */
338
339                 diskstream->flush_playback (start_frame, end_frame);
340
341                 passthru (start_frame, end_frame, nframes, 0);
342
343         } else {
344
345                 /*
346                    XXX is it true that the earlier test on n_outputs()
347                    means that we can avoid checking it again here? i think
348                    so, because changing the i/o configuration of an IO
349                    requires holding the AudioEngine lock, which we hold
350                    while in the process() tree.
351                    */
352
353
354                 /* copy the diskstream data to all output buffers */
355
356                 BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
357                 MidiBuffer& mbuf (bufs.get_midi (0));
358
359                 /* we are a MIDI track, so we always start the chain with a single-channel diskstream */
360                 ChanCount c;
361                 c.set_audio (0);
362                 c.set_midi (1);
363                 bufs.set_count (c);
364
365                 diskstream->get_playback (mbuf, nframes);
366
367                 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
368
369                 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
370
371                 /* final argument: don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
372
373                 process_output_buffers (
374                         bufs, start_frame, end_frame, nframes,
375                         declick, (!diskstream->record_enabled() && !_session.transport_stopped())
376                         );
377         }
378
379         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
380                 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
381                 if (d) {
382                         d->flush_buffers (nframes);
383                 }
384         }
385
386         need_butler = diskstream->commit (playback_distance);
387         
388         return 0;
389 }
390
391 int
392 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
393 {
394         int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
395
396         if (ret == 0 && _step_editing) {
397                 push_midi_input_to_step_edit_ringbuffer (nframes);
398         }
399
400         return ret;
401 }
402
403 void
404 MidiTrack::realtime_locate ()
405 {
406         Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
407
408         if (!lm.locked ()) {
409                 return;
410         }
411
412         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
413                 (*i)->realtime_locate ();
414         }
415
416         midi_diskstream()->reset_tracker ();
417 }
418
419 void
420 MidiTrack::realtime_handle_transport_stopped ()
421 {
422         Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
423
424         if (!lm.locked ()) {
425                 return;
426         }
427
428         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
429                 (*i)->realtime_handle_transport_stopped ();
430         }
431 }
432
433 void
434 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
435 {
436         PortSet& ports (_input->ports());
437
438         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
439
440                 Buffer& b (p->get_buffer (nframes));
441                 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
442                 assert (mb);
443
444                 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
445
446                         const Evoral::MIDIEvent<framepos_t> ev(*e, false);
447
448                         /* note on, since for step edit, note length is determined
449                            elsewhere
450                         */
451
452                         if (ev.is_note_on()) {
453                                 /* we don't care about the time for this purpose */
454                                 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
455                         }
456                 }
457         }
458 }
459
460 void
461 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
462 {
463         MidiBuffer& buf (bufs.get_midi (0));
464
465         // Append immediate events
466
467         if (_immediate_events.read_space()) {
468
469                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
470                                                             name(), _immediate_events.read_space()));
471
472                 /* write as many of the immediate events as we can, but give "true" as
473                  * the last argument ("stop on overflow in destination") so that we'll
474                  * ship the rest out next time.
475                  *
476                  * the (nframes-1) argument puts all these events at the last
477                  * possible position of the output buffer, so that we do not
478                  * violate monotonicity when writing.
479                  */
480
481                 _immediate_events.read (buf, 0, 1, nframes-1, true);
482         }
483 }
484
485 int
486 MidiTrack::export_stuff (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framecnt_t /*nframes*/, 
487                          boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/, bool /*forexport*/)
488 {
489         return -1;
490 }
491
492 boost::shared_ptr<Region>
493 MidiTrack::bounce (InterThreadInfo& /*itt*/)
494 {
495         std::cerr << "MIDI bounce currently unsupported" << std::endl;
496         return boost::shared_ptr<Region> ();
497 }
498
499
500 boost::shared_ptr<Region>
501 MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/,
502                          boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/)
503 {
504         std::cerr << "MIDI bounce range currently unsupported" << std::endl;
505         return boost::shared_ptr<Region> ();
506 }
507
508 void
509 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
510 {
511         std::cerr << "MIDI freeze currently unsupported" << std::endl;
512 }
513
514 void
515 MidiTrack::unfreeze ()
516 {
517         _freeze_record.state = UnFrozen;
518         FreezeChange (); /* EMIT SIGNAL */
519 }
520
521 void
522 MidiTrack::set_note_mode (NoteMode m)
523 {
524         _note_mode = m;
525         midi_diskstream()->set_note_mode(m);
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         const uint32_t type = EventTypeMap::instance().midi_event_type(buf[0]);
552         return (_immediate_events.write(0, type, size, buf) == size);
553 }
554
555 void
556 MidiTrack::MidiControl::set_value(double val)
557 {
558         bool valid = false;
559         if (std::isinf(val)) {
560                 cerr << "MIDIControl value is infinity" << endl;
561         } else if (std::isnan(val)) {
562                 cerr << "MIDIControl value is NaN" << endl;
563         } else if (val < _list->parameter().min()) {
564                 cerr << "MIDIControl value is < " << _list->parameter().min() << endl;
565         } else if (val > _list->parameter().max()) {
566                 cerr << "MIDIControl value is > " << _list->parameter().max() << endl;
567         } else {
568                 valid = true;
569         }
570
571         if (!valid) {
572                 return;
573         }
574
575         assert(val <= _list->parameter().max());
576         if ( ! automation_playback()) {
577                 size_t size = 3;
578                 uint8_t ev[3] = { _list->parameter().channel(), uint8_t (val), 0 };
579                 switch(_list->parameter().type()) {
580                 case MidiCCAutomation:
581                         ev[0] += MIDI_CMD_CONTROL;
582                         ev[1] = _list->parameter().id();
583                         ev[2] = int(val);
584                         break;
585
586                 case MidiPgmChangeAutomation:
587                         size = 2;
588                         ev[0] += MIDI_CMD_PGM_CHANGE;
589                         ev[1] = int(val);
590                         break;
591
592                 case MidiChannelPressureAutomation:
593                         size = 2;
594                         ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
595                         ev[1] = int(val);
596                         break;
597
598                 case MidiPitchBenderAutomation:
599                         ev[0] += MIDI_CMD_BENDER;
600                         ev[1] = 0x7F & int(val);
601                         ev[2] = 0x7F & (int(val) >> 7);
602                         break;
603
604                 default:
605                         assert(false);
606                 }
607                 _route->write_immediate_event(size,  ev);
608         }
609
610         AutomationControl::set_value(val);
611 }
612
613 void
614 MidiTrack::set_step_editing (bool yn)
615 {
616         if (_session.record_status() != Session::Disabled) {
617                 return;
618         }
619
620         if (yn != _step_editing) {
621                 _step_editing = yn;
622                 StepEditStatusChange (yn);
623         }
624 }
625
626 boost::shared_ptr<SMFSource>
627 MidiTrack::write_source (uint32_t)
628 {
629         return midi_diskstream()->write_source ();
630 }
631
632 void
633 MidiTrack::set_channel_mode (ChannelMode mode, uint16_t mask)
634 {
635         midi_diskstream()->set_channel_mode (mode, mask);
636 }
637
638 ChannelMode
639 MidiTrack::get_channel_mode ()
640 {
641         return midi_diskstream()->get_channel_mode ();
642 }
643
644 uint16_t
645 MidiTrack::get_channel_mask ()
646 {
647         return midi_diskstream()->get_channel_mask ();
648 }
649
650 boost::shared_ptr<MidiPlaylist>
651 MidiTrack::midi_playlist ()
652 {
653         return midi_diskstream()->midi_playlist ();
654 }
655
656 void
657 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
658 {
659         DataRecorded (src); /* EMIT SIGNAL */
660 }
661
662 bool
663 MidiTrack::input_active () const
664 {
665         return _input_active;
666 }
667
668 void
669 MidiTrack::set_input_active (bool yn)
670 {
671         if (yn != _input_active) {
672                 _input_active = yn;
673                 map_input_active (yn);
674                 InputActiveChanged (); /* EMIT SIGNAL */
675         }
676 }
677
678 void
679 MidiTrack::map_input_active (bool yn)
680 {
681         if (!_input) {
682                 return;
683         }
684
685         PortSet& ports (_input->ports());
686
687         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
688                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
689                 if (yn != mp->input_active()) {
690                         mp->set_input_active (yn);
691                 }
692         }
693 }
694
695 void
696 MidiTrack::track_input_active (IOChange change, void* /* src */)
697 {
698         if (change.type & IOChange::ConfigurationChanged) {
699                 map_input_active (_input_active);
700         }
701 }
702
703 boost::shared_ptr<Diskstream>
704 MidiTrack::diskstream_factory (XMLNode const & node)
705 {
706         return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
707 }
708
709 boost::shared_ptr<MidiBuffer>
710 MidiTrack::get_gui_feed_buffer () const
711 {
712         return midi_diskstream()->get_gui_feed_buffer ();
713 }
714
715 void
716 MidiTrack::act_on_mute ()
717 {
718         /* this is called right after our mute status has changed.
719            if we are now muted, send suitable output to shutdown
720            all our notes.
721
722            XXX we should should also stop all relevant note trackers.
723         */
724
725         /* If we haven't got a diskstream yet, there's nothing to worry about,
726            and we can't call get_channel_mask() anyway.
727         */
728         if (!midi_diskstream()) {
729                 return;
730         }
731
732         if (muted()) {
733                 /* only send messages for channels we are using */
734
735                 uint16_t mask = get_channel_mask();
736
737                 for (uint8_t channel = 0; channel <= 0xF; channel++) {
738
739                         if ((1<<channel) & mask) {
740
741                                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
742                                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
743                                 write_immediate_event (3, ev);
744                                 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
745                                 write_immediate_event (3, ev);
746                         }
747                 }
748         }
749 }
750         
751 void
752 MidiTrack::set_monitoring (MonitorChoice mc)
753 {
754         if (mc != _monitoring) {
755
756                 Track::set_monitoring (mc);
757                 
758                 /* monitoring state changed, so flush out any on notes at the
759                  * port level.
760                  */
761
762                 PortSet& ports (_output->ports());
763                 
764                 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
765                         boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
766                         if (mp) {
767                                 mp->require_resolve ();
768                         }
769                 }
770
771                 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
772                 
773                 if (md) {
774                         md->reset_tracker ();
775                 }
776         }
777 }
778
779 MonitorState
780 MidiTrack::monitoring_state () const
781 {
782         /* Explicit requests */
783         
784         if (_monitoring & MonitorInput) {
785                 return MonitoringInput;
786         }
787                 
788         if (_monitoring & MonitorDisk) {
789                 return MonitoringDisk;
790         }
791
792         if (_session.transport_rolling()) {
793                 return MonitoringDisk;
794         } 
795
796         /* the return value here doesn't mean that we're actually monitoring
797          * input, let alone input *audio*. but it means that we are NOT 
798          * monitoring silence. this allows us to still hear any audio generated
799          * by using internal generation techniques
800          */
801
802         return MonitoringInput;
803 }