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/meter.h"
41 #include "ardour/midi_diskstream.h"
42 #include "ardour/midi_playlist.h"
43 #include "ardour/midi_port.h"
44 #include "ardour/midi_track.h"
45 #include "ardour/parameter_types.h"
46 #include "ardour/port.h"
47 #include "ardour/processor.h"
48 #include "ardour/session.h"
49 #include "ardour/session_playlists.h"
50 #include "ardour/utils.h"
55 class InterThreadInfo;
62 using namespace ARDOUR;
65 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
66 : Track (sess, name, flag, mode, DataType::MIDI)
67 , _immediate_events(1024) // FIXME: size?
68 , _step_edit_ring_buffer(64) // FIXME: size?
69 , _note_mode(Sustained)
70 , _step_editing (false)
71 , _input_active (true)
72 , _playback_channel_mask(0x0000ffff)
73 , _capture_channel_mask(0x0000ffff)
77 MidiTrack::~MidiTrack ()
88 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
93 boost::shared_ptr<Diskstream>
94 MidiTrack::create_diskstream ()
96 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable);
98 assert(_mode != Destructive);
100 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
105 MidiTrack::set_record_enabled (bool yn, void *src)
111 Track::set_record_enabled (yn, src);
115 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
117 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
118 and the diskstream must be set up to fill its buffers using the correct _note_mode.
120 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
121 mds->set_note_mode (_note_mode);
123 Track::set_diskstream (ds);
125 mds->reset_tracker ();
127 _diskstream->set_track (this);
128 _diskstream->set_destructive (_mode == Destructive);
129 _diskstream->set_record_enabled (false);
131 _diskstream_data_recorded_connection.disconnect ();
132 mds->DataRecorded.connect_same_thread (
133 _diskstream_data_recorded_connection,
134 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
136 DiskstreamChanged (); /* EMIT SIGNAL */
139 boost::shared_ptr<MidiDiskstream>
140 MidiTrack::midi_diskstream() const
142 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
146 MidiTrack::set_state (const XMLNode& node, int version)
148 const XMLProperty *prop;
150 /* This must happen before Track::set_state(), as there will be a buffer
151 fill during that call, and we must fill buffers using the correct
154 if ((prop = node.property (X_("note-mode"))) != 0) {
155 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
157 _note_mode = Sustained;
160 if (Track::set_state (node, version)) {
164 // No destructive MIDI tracks (yet?)
167 if ((prop = node.property ("input-active")) != 0) {
168 set_input_active (string_is_affirmative (prop->value()));
171 ChannelMode playback_channel_mode = AllChannels;
172 ChannelMode capture_channel_mode = AllChannels;
174 if ((prop = node.property ("playback-channel-mode")) != 0) {
175 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
177 if ((prop = node.property ("capture-channel-mode")) != 0) {
178 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
180 if ((prop = node.property ("channel-mode")) != 0) {
181 /* 3.0 behaviour where capture and playback modes were not separated */
182 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
183 capture_channel_mode = playback_channel_mode;
186 unsigned int playback_channel_mask = 0xffff;
187 unsigned int capture_channel_mask = 0xffff;
189 if ((prop = node.property ("playback-channel-mask")) != 0) {
190 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
192 if ((prop = node.property ("capture-channel-mask")) != 0) {
193 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
195 if ((prop = node.property ("channel-mask")) != 0) {
196 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
197 capture_channel_mask = playback_channel_mask;
200 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
201 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
203 pending_state = const_cast<XMLNode*> (&node);
205 if (_session.state_of_the_state() & Session::Loading) {
206 _session.StateReady.connect_same_thread (
207 *this, boost::bind (&MidiTrack::set_state_part_two, this));
209 set_state_part_two ();
216 MidiTrack::state(bool full_state)
218 XMLNode& root (Track::state(full_state));
219 XMLNode* freeze_node;
222 if (_freeze_record.playlist) {
225 freeze_node = new XMLNode (X_("freeze-info"));
226 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
227 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
229 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
230 inode = new XMLNode (X_("processor"));
231 (*i)->id.print (buf, sizeof(buf));
232 inode->add_property (X_("id"), buf);
233 inode->add_child_copy ((*i)->state);
235 freeze_node->add_child_nocopy (*inode);
238 root.add_child_nocopy (*freeze_node);
241 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
242 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
243 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
244 root.add_property("playback-channel-mask", buf);
245 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
246 root.add_property("capture-channel-mask", buf);
248 root.add_property ("note-mode", enum_2_string (_note_mode));
249 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
250 root.add_property ("input-active", (_input_active ? "yes" : "no"));
256 MidiTrack::set_state_part_two ()
260 LocaleGuard lg (X_("POSIX"));
262 /* This is called after all session state has been restored but before
263 have been made ports and connections are established.
266 if (pending_state == 0) {
270 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
272 _freeze_record.state = Frozen;
274 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
277 _freeze_record.processor_info.clear ();
279 if ((prop = fnode->property (X_("playlist"))) != 0) {
280 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
282 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
284 _freeze_record.playlist.reset();
285 _freeze_record.state = NoFreeze;
290 if ((prop = fnode->property (X_("state"))) != 0) {
291 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
294 XMLNodeConstIterator citer;
295 XMLNodeList clist = fnode->children();
297 for (citer = clist.begin(); citer != clist.end(); ++citer) {
298 if ((*citer)->name() != X_("processor")) {
302 if ((prop = (*citer)->property (X_("id"))) == 0) {
306 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
307 boost::shared_ptr<Processor>());
308 frii->id = prop->value ();
309 _freeze_record.processor_info.push_back (frii);
313 if (midi_diskstream ()) {
314 midi_diskstream()->set_block_size (_session.get_block_size ());
320 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
324 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
326 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
328 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
329 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
330 if (can_internal_playback_seek(llabs(playback_distance))) {
331 /* TODO should declick, and/or note-off */
332 internal_playback_seek(playback_distance);
337 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
339 if (n_outputs().n_total() == 0 && _processors.empty()) {
345 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
351 framepos_t transport_frame = _session.transport_frame();
354 framecnt_t playback_distance;
356 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
357 /* need to do this so that the diskstream sets its
358 playback distance to zero, thus causing diskstream::commit
361 BufferSet bufs; /* empty set - is OK, since nothing will happen */
363 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
364 need_butler = diskstream->commit (playback_distance);
368 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
370 fill_buffers_with_input (bufs, _input, nframes);
372 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
373 _meter->run (bufs, start_frame, end_frame, nframes, true);
376 /* filter captured data before the diskstream sees it */
378 filter_channels (bufs, get_capture_channel_mode(), get_capture_channel_mask());
382 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
383 need_butler = diskstream->commit (playback_distance);
388 /* filter playback data before we do anything else */
390 filter_channels (bufs, get_playback_channel_mode(), get_playback_channel_mask ());
392 if (monitoring_state() == MonitoringInput) {
394 /* not actually recording, but we want to hear the input material anyway,
395 at least potentially (depending on monitoring options)
398 /* because the playback buffer is event based and not a
399 * continuous stream, we need to make sure that we empty
400 * it of events every cycle to avoid it filling up with events
401 * read from disk, while we are actually monitoring input
404 diskstream->flush_playback (start_frame, end_frame);
409 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
411 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
413 /* final argument: don't waste time with automation if we're not recording or rolling */
415 process_output_buffers (bufs, start_frame, end_frame, nframes,
416 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
418 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
419 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
421 d->flush_buffers (nframes);
425 need_butler = diskstream->commit (playback_distance);
431 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
433 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
435 if (ret == 0 && _step_editing) {
436 push_midi_input_to_step_edit_ringbuffer (nframes);
443 MidiTrack::realtime_locate ()
445 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
451 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
452 (*i)->realtime_locate ();
455 midi_diskstream()->reset_tracker ();
459 MidiTrack::realtime_handle_transport_stopped ()
461 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
467 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
468 (*i)->realtime_handle_transport_stopped ();
473 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
475 PortSet& ports (_input->ports());
477 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
479 Buffer& b (p->get_buffer (nframes));
480 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
483 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
485 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
487 /* note on, since for step edit, note length is determined
491 if (ev.is_note_on()) {
492 /* we don't care about the time for this purpose */
493 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
500 MidiTrack::filter_channels (BufferSet& bufs, ChannelMode mode, uint32_t mask)
502 if (mode == AllChannels) {
506 MidiBuffer& buf (bufs.get_midi (0));
508 for (MidiBuffer::iterator e = buf.begin(); e != buf.end(); ) {
510 Evoral::MIDIEvent<framepos_t> ev(*e, false);
512 if (ev.is_channel_event()) {
515 if (0 == ((1<<ev.channel()) & mask)) {
522 ev.set_channel (PBD::ffs (mask) - 1);
526 /* handled by the opening if() */
537 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
539 MidiBuffer& buf (bufs.get_midi (0));
541 // Append immediate events
543 if (_immediate_events.read_space()) {
545 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
546 name(), _immediate_events.read_space()));
548 /* write as many of the immediate events as we can, but give "true" as
549 * the last argument ("stop on overflow in destination") so that we'll
550 * ship the rest out next time.
552 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
553 * possible position of the output buffer, so that we do not
554 * violate monotonicity when writing. Port::port_offset() will
555 * be non-zero if we're in a split process cycle.
557 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
562 MidiTrack::export_stuff (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framecnt_t /*nframes*/,
563 boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/, bool /*for_export*/, bool /*for_freeze*/)
568 boost::shared_ptr<Region>
569 MidiTrack::bounce (InterThreadInfo& /*itt*/)
571 std::cerr << "MIDI bounce currently unsupported" << std::endl;
572 return boost::shared_ptr<Region> ();
576 boost::shared_ptr<Region>
577 MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/,
578 boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/)
580 std::cerr << "MIDI bounce range currently unsupported" << std::endl;
581 return boost::shared_ptr<Region> ();
585 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
587 std::cerr << "MIDI freeze currently unsupported" << std::endl;
591 MidiTrack::unfreeze ()
593 _freeze_record.state = UnFrozen;
594 FreezeChange (); /* EMIT SIGNAL */
598 MidiTrack::set_note_mode (NoteMode m)
601 midi_diskstream()->set_note_mode(m);
605 MidiTrack::describe_parameter (Evoral::Parameter param)
607 const std::string str(instrument_info().get_controller_name(param));
608 return str.empty() ? Automatable::describe_parameter(param) : str;
612 MidiTrack::midi_panic()
614 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
615 for (uint8_t channel = 0; channel <= 0xF; channel++) {
616 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
617 write_immediate_event(3, ev);
618 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
619 write_immediate_event(3, ev);
620 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
621 write_immediate_event(3, ev);
625 /** \return true on success, false on failure (no buffer space left)
628 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
630 if (!Evoral::midi_event_is_valid(buf, size)) {
631 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
634 const uint32_t type = midi_parameter_type(buf[0]);
635 return (_immediate_events.write (0, type, size, buf) == size);
639 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
641 switch (param.type()) {
642 case MidiCCAutomation:
643 case MidiPgmChangeAutomation:
644 case MidiPitchBenderAutomation:
645 case MidiChannelPressureAutomation:
646 case MidiSystemExclusiveAutomation:
647 /* The track control for MIDI parameters is for immediate events to act
648 as a control surface, write/touch for them is not currently
652 Automatable::set_parameter_automation_state(param, state);
657 MidiTrack::MidiControl::set_value(double val)
659 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
662 if (isinf_local(val)) {
663 cerr << "MIDIControl value is infinity" << endl;
664 } else if (isnan_local(val)) {
665 cerr << "MIDIControl value is NaN" << endl;
666 } else if (val < parameter.min()) {
667 cerr << "MIDIControl value is < " << parameter.min() << endl;
668 } else if (val > parameter.max()) {
669 cerr << "MIDIControl value is > " << parameter.max() << endl;
678 assert(val <= parameter.max());
679 if ( ! _list || ! automation_playback()) {
681 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
682 switch(parameter.type()) {
683 case MidiCCAutomation:
684 ev[0] += MIDI_CMD_CONTROL;
685 ev[1] = parameter.id();
689 case MidiPgmChangeAutomation:
691 ev[0] += MIDI_CMD_PGM_CHANGE;
695 case MidiChannelPressureAutomation:
697 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
701 case MidiPitchBenderAutomation:
702 ev[0] += MIDI_CMD_BENDER;
703 ev[1] = 0x7F & int(val);
704 ev[2] = 0x7F & (int(val) >> 7);
710 _route->write_immediate_event(size, ev);
713 AutomationControl::set_value(val);
717 MidiTrack::set_step_editing (bool yn)
719 if (_session.record_status() != Session::Disabled) {
723 if (yn != _step_editing) {
725 StepEditStatusChange (yn);
729 boost::shared_ptr<SMFSource>
730 MidiTrack::write_source (uint32_t)
732 return midi_diskstream()->write_source ();
736 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
738 ChannelMode old = get_playback_channel_mode ();
739 uint16_t old_mask = get_playback_channel_mask ();
741 if (old != mode || mask != old_mask) {
742 _set_playback_channel_mode (mode, mask);
743 PlaybackChannelModeChanged ();
744 _session.set_dirty ();
749 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
751 ChannelMode old = get_capture_channel_mode ();
752 uint16_t old_mask = get_capture_channel_mask ();
754 if (old != mode || mask != old_mask) {
755 _set_capture_channel_mode (mode, mask);
756 CaptureChannelModeChanged ();
757 _session.set_dirty ();
762 MidiTrack::set_playback_channel_mask (uint16_t mask)
764 uint16_t old = get_playback_channel_mask();
767 _set_playback_channel_mask (mask);
768 PlaybackChannelMaskChanged ();
769 _session.set_dirty ();
774 MidiTrack::set_capture_channel_mask (uint16_t mask)
776 uint16_t old = get_capture_channel_mask();
779 _set_capture_channel_mask (mask);
780 CaptureChannelMaskChanged ();
781 _session.set_dirty ();
785 boost::shared_ptr<MidiPlaylist>
786 MidiTrack::midi_playlist ()
788 return midi_diskstream()->midi_playlist ();
792 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
794 DataRecorded (src); /* EMIT SIGNAL */
798 MidiTrack::input_active () const
800 return _input_active;
804 MidiTrack::set_input_active (bool yn)
806 if (yn != _input_active) {
808 map_input_active (yn);
809 InputActiveChanged (); /* EMIT SIGNAL */
814 MidiTrack::map_input_active (bool yn)
820 PortSet& ports (_input->ports());
822 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
823 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
824 if (yn != mp->input_active()) {
825 mp->set_input_active (yn);
831 MidiTrack::track_input_active (IOChange change, void* /* src */)
833 if (change.type & IOChange::ConfigurationChanged) {
834 map_input_active (_input_active);
838 boost::shared_ptr<Diskstream>
839 MidiTrack::diskstream_factory (XMLNode const & node)
841 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
844 boost::shared_ptr<MidiBuffer>
845 MidiTrack::get_gui_feed_buffer () const
847 return midi_diskstream()->get_gui_feed_buffer ();
851 MidiTrack::act_on_mute ()
853 /* this is called right after our mute status has changed.
854 if we are now muted, send suitable output to shutdown
857 XXX we should should also stop all relevant note trackers.
860 /* If we haven't got a diskstream yet, there's nothing to worry about,
861 and we can't call get_channel_mask() anyway.
863 if (!midi_diskstream()) {
868 /* only send messages for channels we are using */
870 uint16_t mask = get_playback_channel_mask();
872 for (uint8_t channel = 0; channel <= 0xF; channel++) {
874 if ((1<<channel) & mask) {
876 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
877 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
878 write_immediate_event (3, ev);
879 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
880 write_immediate_event (3, ev);
887 MidiTrack::set_monitoring (MonitorChoice mc)
889 if (mc != _monitoring) {
891 Track::set_monitoring (mc);
893 /* monitoring state changed, so flush out any on notes at the
897 PortSet& ports (_output->ports());
899 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
900 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
902 mp->require_resolve ();
906 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
909 md->reset_tracker ();
915 MidiTrack::monitoring_state () const
917 MonitorState ms = Track::monitoring_state();
918 if (ms == MonitoringSilence) {
919 return MonitoringInput;