2 Copyright (C) 2006 Paul Davis
3 Author: David Robillard
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.
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.
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.
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)
28 #define isinf_local std::isinf
29 #define isnan_local std::isnan
33 #include "pbd/enumwriter.h"
34 #include "pbd/convert.h"
35 #include "evoral/midi_util.h"
37 #include "ardour/buffer_set.h"
38 #include "ardour/debug.h"
39 #include "ardour/delivery.h"
40 #include "ardour/event_type_map.h"
41 #include "ardour/meter.h"
42 #include "ardour/midi_diskstream.h"
43 #include "ardour/midi_playlist.h"
44 #include "ardour/midi_port.h"
45 #include "ardour/midi_track.h"
46 #include "ardour/parameter_types.h"
47 #include "ardour/port.h"
48 #include "ardour/processor.h"
49 #include "ardour/session.h"
50 #include "ardour/session_playlists.h"
51 #include "ardour/utils.h"
56 class InterThreadInfo;
63 using namespace ARDOUR;
66 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
67 : Track (sess, name, flag, mode, DataType::MIDI)
68 , _immediate_events(1024) // FIXME: size?
69 , _step_edit_ring_buffer(64) // FIXME: size?
70 , _note_mode(Sustained)
71 , _step_editing (false)
72 , _input_active (true)
73 , _playback_channel_mask(0x0000ffff)
74 , _capture_channel_mask(0x0000ffff)
78 MidiTrack::~MidiTrack ()
89 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
94 boost::shared_ptr<Diskstream>
95 MidiTrack::create_diskstream ()
97 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable);
99 assert(_mode != Destructive);
101 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
106 MidiTrack::set_record_enabled (bool yn, void *src)
112 Track::set_record_enabled (yn, src);
116 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
118 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
119 and the diskstream must be set up to fill its buffers using the correct _note_mode.
121 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
122 mds->set_note_mode (_note_mode);
124 Track::set_diskstream (ds);
126 mds->reset_tracker ();
128 _diskstream->set_track (this);
129 _diskstream->set_destructive (_mode == Destructive);
130 _diskstream->set_record_enabled (false);
132 _diskstream_data_recorded_connection.disconnect ();
133 mds->DataRecorded.connect_same_thread (
134 _diskstream_data_recorded_connection,
135 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
137 DiskstreamChanged (); /* EMIT SIGNAL */
140 boost::shared_ptr<MidiDiskstream>
141 MidiTrack::midi_diskstream() const
143 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
147 MidiTrack::set_state (const XMLNode& node, int version)
149 const XMLProperty *prop;
151 /* This must happen before Track::set_state(), as there will be a buffer
152 fill during that call, and we must fill buffers using the correct
155 if ((prop = node.property (X_("note-mode"))) != 0) {
156 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
158 _note_mode = Sustained;
161 if (Track::set_state (node, version)) {
165 // No destructive MIDI tracks (yet?)
168 if ((prop = node.property ("input-active")) != 0) {
169 set_input_active (string_is_affirmative (prop->value()));
172 ChannelMode playback_channel_mode = AllChannels;
173 ChannelMode capture_channel_mode = AllChannels;
175 if ((prop = node.property ("playback-channel-mode")) != 0) {
176 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
178 if ((prop = node.property ("capture-channel-mode")) != 0) {
179 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
181 if ((prop = node.property ("channel-mode")) != 0) {
182 /* 3.0 behaviour where capture and playback modes were not separated */
183 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
184 capture_channel_mode = playback_channel_mode;
187 unsigned int playback_channel_mask = 0xffff;
188 unsigned int capture_channel_mask = 0xffff;
190 if ((prop = node.property ("playback-channel-mask")) != 0) {
191 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
193 if ((prop = node.property ("capture-channel-mask")) != 0) {
194 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
196 if ((prop = node.property ("channel-mask")) != 0) {
197 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
198 capture_channel_mask = playback_channel_mask;
201 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
202 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
204 pending_state = const_cast<XMLNode*> (&node);
206 if (_session.state_of_the_state() & Session::Loading) {
207 _session.StateReady.connect_same_thread (
208 *this, boost::bind (&MidiTrack::set_state_part_two, this));
210 set_state_part_two ();
217 MidiTrack::state(bool full_state)
219 XMLNode& root (Track::state(full_state));
220 XMLNode* freeze_node;
223 if (_freeze_record.playlist) {
226 freeze_node = new XMLNode (X_("freeze-info"));
227 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
228 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
230 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
231 inode = new XMLNode (X_("processor"));
232 (*i)->id.print (buf, sizeof(buf));
233 inode->add_property (X_("id"), buf);
234 inode->add_child_copy ((*i)->state);
236 freeze_node->add_child_nocopy (*inode);
239 root.add_child_nocopy (*freeze_node);
242 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
243 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
244 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
245 root.add_property("playback-channel-mask", buf);
246 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
247 root.add_property("capture-channel-mask", buf);
249 root.add_property ("note-mode", enum_2_string (_note_mode));
250 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
251 root.add_property ("input-active", (_input_active ? "yes" : "no"));
257 MidiTrack::set_state_part_two ()
261 LocaleGuard lg (X_("POSIX"));
263 /* This is called after all session state has been restored but before
264 have been made ports and connections are established.
267 if (pending_state == 0) {
271 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
273 _freeze_record.state = Frozen;
275 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
278 _freeze_record.processor_info.clear ();
280 if ((prop = fnode->property (X_("playlist"))) != 0) {
281 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
283 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
285 _freeze_record.playlist.reset();
286 _freeze_record.state = NoFreeze;
291 if ((prop = fnode->property (X_("state"))) != 0) {
292 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
295 XMLNodeConstIterator citer;
296 XMLNodeList clist = fnode->children();
298 for (citer = clist.begin(); citer != clist.end(); ++citer) {
299 if ((*citer)->name() != X_("processor")) {
303 if ((prop = (*citer)->property (X_("id"))) == 0) {
307 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
308 boost::shared_ptr<Processor>());
309 frii->id = prop->value ();
310 _freeze_record.processor_info.push_back (frii);
314 if (midi_diskstream ()) {
315 midi_diskstream()->set_block_size (_session.get_block_size ());
321 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
325 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
327 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
329 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
330 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
331 if (can_internal_playback_seek(llabs(playback_distance))) {
332 /* TODO should declick, and/or note-off */
333 internal_playback_seek(playback_distance);
338 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
340 if (n_outputs().n_total() == 0 && _processors.empty()) {
346 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
352 framepos_t transport_frame = _session.transport_frame();
355 framecnt_t playback_distance;
357 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
358 /* need to do this so that the diskstream sets its
359 playback distance to zero, thus causing diskstream::commit
362 BufferSet bufs; /* empty set - is OK, since nothing will happen */
364 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
365 need_butler = diskstream->commit (playback_distance);
369 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
371 fill_buffers_with_input (bufs, _input, nframes);
373 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
374 _meter->run (bufs, start_frame, end_frame, nframes, true);
377 /* filter captured data before the diskstream sees it */
379 filter_channels (bufs, get_capture_channel_mode(), get_capture_channel_mask());
383 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
384 need_butler = diskstream->commit (playback_distance);
389 /* filter playback data before we do anything else */
391 filter_channels (bufs, get_playback_channel_mode(), get_playback_channel_mask ());
393 if (monitoring_state() == MonitoringInput) {
395 /* not actually recording, but we want to hear the input material anyway,
396 at least potentially (depending on monitoring options)
399 /* because the playback buffer is event based and not a
400 * continuous stream, we need to make sure that we empty
401 * it of events every cycle to avoid it filling up with events
402 * read from disk, while we are actually monitoring input
405 diskstream->flush_playback (start_frame, end_frame);
410 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
412 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
414 /* final argument: don't waste time with automation if we're not recording or rolling */
416 process_output_buffers (bufs, start_frame, end_frame, nframes,
417 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
419 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
420 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
422 d->flush_buffers (nframes);
426 need_butler = diskstream->commit (playback_distance);
432 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
434 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
436 if (ret == 0 && _step_editing) {
437 push_midi_input_to_step_edit_ringbuffer (nframes);
444 MidiTrack::realtime_locate ()
446 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
452 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
453 (*i)->realtime_locate ();
456 midi_diskstream()->reset_tracker ();
460 MidiTrack::realtime_handle_transport_stopped ()
462 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
468 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
469 (*i)->realtime_handle_transport_stopped ();
474 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
476 PortSet& ports (_input->ports());
478 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
480 Buffer& b (p->get_buffer (nframes));
481 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
484 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
486 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
488 /* note on, since for step edit, note length is determined
492 if (ev.is_note_on()) {
493 /* we don't care about the time for this purpose */
494 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
501 MidiTrack::filter_channels (BufferSet& bufs, ChannelMode mode, uint32_t mask)
503 if (mode == AllChannels) {
507 MidiBuffer& buf (bufs.get_midi (0));
509 for (MidiBuffer::iterator e = buf.begin(); e != buf.end(); ) {
511 Evoral::MIDIEvent<framepos_t> ev(*e, false);
513 if (ev.is_channel_event()) {
516 if (0 == ((1<<ev.channel()) & mask)) {
523 ev.set_channel (PBD::ffs (mask) - 1);
527 /* handled by the opening if() */
538 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
540 MidiBuffer& buf (bufs.get_midi (0));
542 // Append immediate events
544 if (_immediate_events.read_space()) {
546 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
547 name(), _immediate_events.read_space()));
549 /* write as many of the immediate events as we can, but give "true" as
550 * the last argument ("stop on overflow in destination") so that we'll
551 * ship the rest out next time.
553 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
554 * possible position of the output buffer, so that we do not
555 * violate monotonicity when writing. Port::port_offset() will
556 * be non-zero if we're in a split process cycle.
558 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
563 MidiTrack::export_stuff (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framecnt_t /*nframes*/,
564 boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/, bool /*for_export*/, bool /*for_freeze*/)
569 boost::shared_ptr<Region>
570 MidiTrack::bounce (InterThreadInfo& /*itt*/)
572 std::cerr << "MIDI bounce currently unsupported" << std::endl;
573 return boost::shared_ptr<Region> ();
577 boost::shared_ptr<Region>
578 MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/,
579 boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/)
581 std::cerr << "MIDI bounce range currently unsupported" << std::endl;
582 return boost::shared_ptr<Region> ();
586 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
588 std::cerr << "MIDI freeze currently unsupported" << std::endl;
592 MidiTrack::unfreeze ()
594 _freeze_record.state = UnFrozen;
595 FreezeChange (); /* EMIT SIGNAL */
599 MidiTrack::set_note_mode (NoteMode m)
602 midi_diskstream()->set_note_mode(m);
606 MidiTrack::describe_parameter (Evoral::Parameter param)
608 const std::string str(instrument_info().get_controller_name(param));
609 return str.empty() ? Automatable::describe_parameter(param) : str;
613 MidiTrack::midi_panic()
615 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
616 for (uint8_t channel = 0; channel <= 0xF; channel++) {
617 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
618 write_immediate_event(3, ev);
619 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
620 write_immediate_event(3, ev);
621 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
622 write_immediate_event(3, ev);
626 /** \return true on success, false on failure (no buffer space left)
629 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
631 if (!Evoral::midi_event_is_valid(buf, size)) {
632 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
635 const uint32_t type = midi_parameter_type(buf[0]);
636 return (_immediate_events.write (0, type, size, buf) == size);
640 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
642 switch (param.type()) {
643 case MidiCCAutomation:
644 case MidiPgmChangeAutomation:
645 case MidiPitchBenderAutomation:
646 case MidiChannelPressureAutomation:
647 case MidiSystemExclusiveAutomation:
648 /* The track control for MIDI parameters is for immediate events to act
649 as a control surface, write/touch for them is not currently
653 Automatable::set_parameter_automation_state(param, state);
658 MidiTrack::MidiControl::set_value(double val)
660 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
661 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
664 if (isinf_local(val)) {
665 cerr << "MIDIControl value is infinity" << endl;
666 } else if (isnan_local(val)) {
667 cerr << "MIDIControl value is NaN" << endl;
668 } else if (val < desc.lower) {
669 cerr << "MIDIControl value is < " << desc.lower << endl;
670 } else if (val > desc.upper) {
671 cerr << "MIDIControl value is > " << desc.upper << endl;
680 assert(val <= desc.upper);
681 if ( ! _list || ! automation_playback()) {
683 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
684 switch(parameter.type()) {
685 case MidiCCAutomation:
686 ev[0] += MIDI_CMD_CONTROL;
687 ev[1] = parameter.id();
691 case MidiPgmChangeAutomation:
693 ev[0] += MIDI_CMD_PGM_CHANGE;
697 case MidiChannelPressureAutomation:
699 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
703 case MidiPitchBenderAutomation:
704 ev[0] += MIDI_CMD_BENDER;
705 ev[1] = 0x7F & int(val);
706 ev[2] = 0x7F & (int(val) >> 7);
712 _route->write_immediate_event(size, ev);
715 AutomationControl::set_value(val);
719 MidiTrack::set_step_editing (bool yn)
721 if (_session.record_status() != Session::Disabled) {
725 if (yn != _step_editing) {
727 StepEditStatusChange (yn);
731 boost::shared_ptr<SMFSource>
732 MidiTrack::write_source (uint32_t)
734 return midi_diskstream()->write_source ();
738 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
740 ChannelMode old = get_playback_channel_mode ();
741 uint16_t old_mask = get_playback_channel_mask ();
743 if (old != mode || mask != old_mask) {
744 _set_playback_channel_mode (mode, mask);
745 PlaybackChannelModeChanged ();
746 _session.set_dirty ();
751 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
753 ChannelMode old = get_capture_channel_mode ();
754 uint16_t old_mask = get_capture_channel_mask ();
756 if (old != mode || mask != old_mask) {
757 _set_capture_channel_mode (mode, mask);
758 CaptureChannelModeChanged ();
759 _session.set_dirty ();
764 MidiTrack::set_playback_channel_mask (uint16_t mask)
766 uint16_t old = get_playback_channel_mask();
769 _set_playback_channel_mask (mask);
770 PlaybackChannelMaskChanged ();
771 _session.set_dirty ();
776 MidiTrack::set_capture_channel_mask (uint16_t mask)
778 uint16_t old = get_capture_channel_mask();
781 _set_capture_channel_mask (mask);
782 CaptureChannelMaskChanged ();
783 _session.set_dirty ();
787 boost::shared_ptr<MidiPlaylist>
788 MidiTrack::midi_playlist ()
790 return midi_diskstream()->midi_playlist ();
794 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
796 DataRecorded (src); /* EMIT SIGNAL */
800 MidiTrack::input_active () const
802 return _input_active;
806 MidiTrack::set_input_active (bool yn)
808 if (yn != _input_active) {
810 map_input_active (yn);
811 InputActiveChanged (); /* EMIT SIGNAL */
816 MidiTrack::map_input_active (bool yn)
822 PortSet& ports (_input->ports());
824 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
825 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
826 if (yn != mp->input_active()) {
827 mp->set_input_active (yn);
833 MidiTrack::track_input_active (IOChange change, void* /* src */)
835 if (change.type & IOChange::ConfigurationChanged) {
836 map_input_active (_input_active);
840 boost::shared_ptr<Diskstream>
841 MidiTrack::diskstream_factory (XMLNode const & node)
843 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
846 boost::shared_ptr<MidiBuffer>
847 MidiTrack::get_gui_feed_buffer () const
849 return midi_diskstream()->get_gui_feed_buffer ();
853 MidiTrack::act_on_mute ()
855 /* this is called right after our mute status has changed.
856 if we are now muted, send suitable output to shutdown
859 XXX we should should also stop all relevant note trackers.
862 /* If we haven't got a diskstream yet, there's nothing to worry about,
863 and we can't call get_channel_mask() anyway.
865 if (!midi_diskstream()) {
870 /* only send messages for channels we are using */
872 uint16_t mask = get_playback_channel_mask();
874 for (uint8_t channel = 0; channel <= 0xF; channel++) {
876 if ((1<<channel) & mask) {
878 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
879 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
880 write_immediate_event (3, ev);
881 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
882 write_immediate_event (3, ev);
889 MidiTrack::set_monitoring (MonitorChoice mc)
891 if (mc != _monitoring) {
893 Track::set_monitoring (mc);
895 /* monitoring state changed, so flush out any on notes at the
899 PortSet& ports (_output->ports());
901 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
902 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
904 mp->require_resolve ();
908 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
911 md->reset_tracker ();
917 MidiTrack::monitoring_state () const
919 MonitorState ms = Track::monitoring_state();
920 if (ms == MonitoringSilence) {
921 return MonitoringInput;