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
32 #include "pbd/enumwriter.h"
33 #include "pbd/types_convert.h"
34 #include "evoral/midi_util.h"
36 #include "ardour/beats_frames_converter.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_region.h"
46 #include "ardour/midi_track.h"
47 #include "ardour/monitor_control.h"
48 #include "ardour/parameter_types.h"
49 #include "ardour/port.h"
50 #include "ardour/processor.h"
51 #include "ardour/profile.h"
52 #include "ardour/route_group_specialized.h"
53 #include "ardour/session.h"
54 #include "ardour/session_playlists.h"
55 #include "ardour/types_convert.h"
56 #include "ardour/utils.h"
61 class InterThreadInfo;
68 using namespace ARDOUR;
71 MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
72 : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
73 , _immediate_events(6096) // FIXME: size?
74 , _step_edit_ring_buffer(64) // FIXME: size?
75 , _note_mode(Sustained)
76 , _step_editing (false)
77 , _input_active (true)
79 _session.SessionLoaded.connect_same_thread (*this, boost::bind (&MidiTrack::restore_controls, this));
82 MidiTrack::~MidiTrack ()
93 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
98 boost::shared_ptr<Diskstream>
99 MidiTrack::create_diskstream ()
101 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable);
103 assert(_mode != Destructive);
105 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
110 MidiTrack::can_be_record_safe ()
116 return Track::can_be_record_safe ();
120 MidiTrack::can_be_record_enabled ()
126 return Track::can_be_record_enabled ();
130 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
132 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
133 and the diskstream must be set up to fill its buffers using the correct _note_mode.
135 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
136 mds->set_note_mode (_note_mode);
138 Track::set_diskstream (ds);
140 mds->reset_tracker ();
142 _diskstream->set_track (this);
143 #ifdef XXX_OLD_DESTRUCTIVE_API_XXX
144 if (Profile->get_trx()) {
145 _diskstream->set_destructive (false);
147 _diskstream->set_destructive (_mode == Destructive);
150 _diskstream->set_record_enabled (false);
152 _diskstream_data_recorded_connection.disconnect ();
153 mds->DataRecorded.connect_same_thread (
154 _diskstream_data_recorded_connection,
155 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
157 DiskstreamChanged (); /* EMIT SIGNAL */
160 boost::shared_ptr<MidiDiskstream>
161 MidiTrack::midi_diskstream() const
163 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
167 MidiTrack::set_state (const XMLNode& node, int version)
169 /* This must happen before Track::set_state(), as there will be a buffer
170 fill during that call, and we must fill buffers using the correct
173 if (!node.get_property (X_("note-mode"), _note_mode)) {
174 _note_mode = Sustained;
177 if (Track::set_state (node, version)) {
181 // No destructive MIDI tracks (yet?)
185 if (node.get_property ("input-active", yn)) {
186 set_input_active (yn);
189 ChannelMode playback_channel_mode = AllChannels;
190 ChannelMode capture_channel_mode = AllChannels;
192 node.get_property ("playback-channel-mode", playback_channel_mode);
193 node.get_property ("capture-channel-mode", capture_channel_mode);
195 if (node.get_property ("channel-mode", playback_channel_mode)) {
196 /* 3.0 behaviour where capture and playback modes were not separated */
197 capture_channel_mode = playback_channel_mode;
200 XMLProperty const * prop;
202 unsigned int playback_channel_mask = 0xffff;
203 unsigned int capture_channel_mask = 0xffff;
205 if ((prop = node.property ("playback-channel-mask")) != 0) {
206 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
208 if ((prop = node.property ("capture-channel-mask")) != 0) {
209 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
211 if ((prop = node.property ("channel-mask")) != 0) {
212 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
213 capture_channel_mask = playback_channel_mask;
216 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
217 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
219 pending_state = const_cast<XMLNode*> (&node);
221 if (_session.state_of_the_state() & Session::Loading) {
222 _session.StateReady.connect_same_thread (
223 *this, boost::bind (&MidiTrack::set_state_part_two, this));
225 set_state_part_two ();
232 MidiTrack::state(bool full_state)
234 XMLNode& root (Track::state(full_state));
235 XMLNode* freeze_node;
238 if (_freeze_record.playlist) {
241 freeze_node = new XMLNode (X_("freeze-info"));
242 freeze_node->set_property ("playlist", _freeze_record.playlist->name());
243 freeze_node->set_property ("state", _freeze_record.state);
245 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
246 inode = new XMLNode (X_("processor"));
247 inode->set_property (X_("id"), id());
248 inode->add_child_copy ((*i)->state);
250 freeze_node->add_child_nocopy (*inode);
253 root.add_child_nocopy (*freeze_node);
256 root.set_property("playback-channel-mode", get_playback_channel_mode());
257 root.set_property("capture-channel-mode", get_capture_channel_mode());
258 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
259 root.set_property("playback-channel-mask", std::string(buf));
260 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
261 root.set_property("capture-channel-mask", std::string(buf));
263 root.set_property ("note-mode", _note_mode);
264 root.set_property ("step-editing", _step_editing);
265 root.set_property ("input-active", _input_active);
267 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
268 if (boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) {
269 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c->second);
271 root.add_child_nocopy (ac->get_state ());
279 MidiTrack::set_state_part_two ()
284 /* This is called after all session state has been restored but before
285 have been made ports and connections are established.
288 if (pending_state == 0) {
292 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
294 _freeze_record.state = Frozen;
296 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
299 _freeze_record.processor_info.clear ();
302 if (fnode->get_property (X_("playlist"), str)) {
303 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (str);
305 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
307 _freeze_record.playlist.reset();
308 _freeze_record.state = NoFreeze;
313 fnode->get_property (X_("state"), _freeze_record.state);
315 XMLNodeConstIterator citer;
316 XMLNodeList clist = fnode->children();
318 for (citer = clist.begin(); citer != clist.end(); ++citer) {
319 if ((*citer)->name() != X_("processor")) {
323 if (!(*citer)->get_property (X_("id"), str)) {
327 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
328 boost::shared_ptr<Processor>());
330 _freeze_record.processor_info.push_back (frii);
334 if (midi_diskstream ()) {
335 midi_diskstream()->set_block_size (_session.get_block_size ());
342 MidiTrack::restore_controls ()
344 // TODO order events (CC before PGM to set banks)
345 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
346 boost::shared_ptr<MidiTrack::MidiControl> mctrl = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second);
348 mctrl->restore_value();
354 MidiTrack::update_controls(const BufferSet& bufs)
356 const MidiBuffer& buf = bufs.get_midi(0);
357 for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
358 const Evoral::Event<framepos_t>& ev = *e;
359 const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
360 const boost::shared_ptr<Evoral::Control> control = this->control(param);
362 control->set_double(ev.value(), _session.transport_frame(), false);
367 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
371 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
373 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
375 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
376 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
377 if (can_internal_playback_seek(::llabs(playback_distance))) {
378 /* TODO should declick, and/or note-off */
379 internal_playback_seek(playback_distance);
384 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
386 if (n_outputs().n_total() == 0 && _processors.empty()) {
392 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
398 framepos_t transport_frame = _session.transport_frame();
401 framecnt_t playback_distance;
403 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
404 /* need to do this so that the diskstream sets its
405 playback distance to zero, thus causing diskstream::commit
408 BufferSet bufs; /* empty set - is OK, since nothing will happen */
410 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
411 need_butler = diskstream->commit (playback_distance);
415 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
417 fill_buffers_with_input (bufs, _input, nframes);
419 /* filter captured data before meter sees it */
420 _capture_filter.filter (bufs);
422 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
423 _meter->run (bufs, start_frame, end_frame, 1.0 /*speed()*/, nframes, true);
429 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
430 need_butler = diskstream->commit (playback_distance);
435 /* note diskstream uses our filter to filter/map playback channels appropriately. */
437 if (monitoring_state() == MonitoringInput) {
439 /* not actually recording, but we want to hear the input material anyway,
440 at least potentially (depending on monitoring options)
443 /* because the playback buffer is event based and not a
444 * continuous stream, we need to make sure that we empty
445 * it of events every cycle to avoid it filling up with events
446 * read from disk, while we are actually monitoring input
449 diskstream->flush_playback (start_frame, end_frame);
454 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
456 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
458 /* final argument: don't waste time with automation if we're not recording or rolling */
460 process_output_buffers (bufs, start_frame, end_frame, nframes,
461 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
463 flush_processor_buffers_locked (nframes);
465 need_butler = diskstream->commit (playback_distance);
471 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
473 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
475 if (ret == 0 && _step_editing) {
476 push_midi_input_to_step_edit_ringbuffer (nframes);
483 MidiTrack::realtime_locate ()
485 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
491 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
492 (*i)->realtime_locate ();
495 midi_diskstream()->reset_tracker ();
499 MidiTrack::realtime_handle_transport_stopped ()
501 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
507 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
508 (*i)->realtime_handle_transport_stopped ();
513 MidiTrack::non_realtime_locate (framepos_t pos)
515 Track::non_realtime_locate(pos);
517 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
522 /* Get the top unmuted region at this position. */
523 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
524 playlist->top_unmuted_region_at(pos));
529 /* the source may be missing, but the control still referenced in the GUI */
530 if (!region->midi_source() || !region->model()) {
534 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
539 /* Update track controllers based on its "automation". */
540 const framepos_t origin = region->position() - region->start();
541 BeatsFramesConverter bfc(_session.tempo_map(), origin);
542 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
543 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
544 boost::shared_ptr<Evoral::Control> rcontrol;
545 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
546 (rcontrol = region->control(tcontrol->parameter()))) {
547 const Evoral::Beats pos_beats = bfc.from(pos - origin);
548 if (rcontrol->list()->size() > 0) {
549 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
556 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
558 PortSet& ports (_input->ports());
560 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
562 Buffer& b (p->get_buffer (nframes));
563 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
566 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
568 const Evoral::Event<framepos_t> ev(*e, false);
570 /* note on, since for step edit, note length is determined
574 if (ev.is_note_on()) {
575 /* we don't care about the time for this purpose */
576 _step_edit_ring_buffer.write (0, ev.event_type(), ev.size(), ev.buffer());
583 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
585 MidiBuffer& buf (bufs.get_midi (0));
587 update_controls (bufs);
589 // Append immediate events
591 if (_immediate_events.read_space()) {
593 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
594 name(), _immediate_events.read_space()));
596 /* write as many of the immediate events as we can, but give "true" as
597 * the last argument ("stop on overflow in destination") so that we'll
598 * ship the rest out next time.
600 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
601 * possible position of the output buffer, so that we do not
602 * violate monotonicity when writing. Port::port_offset() will
603 * be non-zero if we're in a split process cycle.
605 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
610 MidiTrack::export_stuff (BufferSet& buffers,
613 boost::shared_ptr<Processor> endpoint,
614 bool include_endpoint,
618 if (buffers.count().n_midi() == 0) {
622 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
624 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
626 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
631 buffers.get_midi(0).clear();
632 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
636 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
641 boost::shared_ptr<Region>
642 MidiTrack::bounce (InterThreadInfo& itt)
644 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
647 boost::shared_ptr<Region>
648 MidiTrack::bounce_range (framepos_t start,
650 InterThreadInfo& itt,
651 boost::shared_ptr<Processor> endpoint,
652 bool include_endpoint)
654 vector<boost::shared_ptr<Source> > srcs;
655 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
659 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
661 std::cerr << "MIDI freeze currently unsupported" << std::endl;
665 MidiTrack::unfreeze ()
667 _freeze_record.state = UnFrozen;
668 FreezeChange (); /* EMIT SIGNAL */
672 MidiTrack::set_note_mode (NoteMode m)
675 midi_diskstream()->set_note_mode(m);
679 MidiTrack::describe_parameter (Evoral::Parameter param)
681 const std::string str(instrument_info().get_controller_name(param));
682 return str.empty() ? Automatable::describe_parameter(param) : str;
686 MidiTrack::midi_panic()
688 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
689 for (uint8_t channel = 0; channel <= 0xF; channel++) {
690 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
691 write_immediate_event(3, ev);
692 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
693 write_immediate_event(3, ev);
694 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
695 write_immediate_event(3, ev);
699 /** \return true on success, false on failure (no buffer space left)
702 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
704 if (!Evoral::midi_event_is_valid(buf, size)) {
705 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
708 return (_immediate_events.write (0, Evoral::MIDI_EVENT, size, buf) == size);
712 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
714 switch (param.type()) {
715 case MidiCCAutomation:
716 case MidiPgmChangeAutomation:
717 case MidiPitchBenderAutomation:
718 case MidiChannelPressureAutomation:
719 case MidiNotePressureAutomation:
720 case MidiSystemExclusiveAutomation:
721 /* The track control for MIDI parameters is for immediate events to act
722 as a control surface, write/touch for them is not currently
726 Automatable::set_parameter_automation_state(param, state);
731 MidiTrack::MidiControl::restore_value ()
733 actually_set_value (get_value(), Controllable::NoGroup);
737 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
739 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
740 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
743 if (isinf_local(val)) {
744 cerr << "MIDIControl value is infinity" << endl;
745 } else if (isnan_local(val)) {
746 cerr << "MIDIControl value is NaN" << endl;
747 } else if (val < desc.lower) {
748 cerr << "MIDIControl value is < " << desc.lower << endl;
749 } else if (val > desc.upper) {
750 cerr << "MIDIControl value is > " << desc.upper << endl;
759 assert(val <= desc.upper);
760 if ( ! _list || ! automation_playback()) {
762 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
763 switch(parameter.type()) {
764 case MidiCCAutomation:
765 ev[0] += MIDI_CMD_CONTROL;
766 ev[1] = parameter.id();
770 case MidiPgmChangeAutomation:
772 ev[0] += MIDI_CMD_PGM_CHANGE;
776 case MidiChannelPressureAutomation:
778 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
782 case MidiNotePressureAutomation:
783 ev[0] += MIDI_CMD_NOTE_PRESSURE;
784 ev[1] = parameter.id();
788 case MidiPitchBenderAutomation:
789 ev[0] += MIDI_CMD_BENDER;
790 ev[1] = 0x7F & int(val);
791 ev[2] = 0x7F & (int(val) >> 7);
797 _route->write_immediate_event(size, ev);
800 AutomationControl::actually_set_value(val, group_override);
804 MidiTrack::set_step_editing (bool yn)
806 if (_session.record_status() != Session::Disabled) {
810 if (yn != _step_editing) {
812 StepEditStatusChange (yn);
816 boost::shared_ptr<SMFSource>
817 MidiTrack::write_source (uint32_t)
819 return midi_diskstream()->write_source ();
823 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
825 if (_playback_filter.set_channel_mode(mode, mask)) {
826 _session.set_dirty();
831 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
833 if (_capture_filter.set_channel_mode(mode, mask)) {
834 _session.set_dirty();
839 MidiTrack::set_playback_channel_mask (uint16_t mask)
841 if (_playback_filter.set_channel_mask(mask)) {
842 _session.set_dirty();
847 MidiTrack::set_capture_channel_mask (uint16_t mask)
849 if (_capture_filter.set_channel_mask(mask)) {
850 _session.set_dirty();
854 boost::shared_ptr<MidiPlaylist>
855 MidiTrack::midi_playlist ()
857 return midi_diskstream()->midi_playlist ();
861 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
863 DataRecorded (src); /* EMIT SIGNAL */
867 MidiTrack::input_active () const
869 return _input_active;
873 MidiTrack::set_input_active (bool yn)
875 if (yn != _input_active) {
877 map_input_active (yn);
878 InputActiveChanged (); /* EMIT SIGNAL */
883 MidiTrack::map_input_active (bool yn)
889 PortSet& ports (_input->ports());
891 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
892 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
893 if (yn != mp->input_active()) {
894 mp->set_input_active (yn);
900 MidiTrack::track_input_active (IOChange change, void* /* src */)
902 if (change.type & IOChange::ConfigurationChanged) {
903 map_input_active (_input_active);
907 boost::shared_ptr<Diskstream>
908 MidiTrack::diskstream_factory (XMLNode const & node)
910 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
913 boost::shared_ptr<MidiBuffer>
914 MidiTrack::get_gui_feed_buffer () const
916 return midi_diskstream()->get_gui_feed_buffer ();
920 MidiTrack::act_on_mute ()
922 /* this is called right after our mute status has changed.
923 if we are now muted, send suitable output to shutdown
926 XXX we should should also stop all relevant note trackers.
929 /* If we haven't got a diskstream yet, there's nothing to worry about,
930 and we can't call get_channel_mask() anyway.
932 if (!midi_diskstream()) {
936 if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
937 /* only send messages for channels we are using */
939 uint16_t mask = _playback_filter.get_channel_mask();
941 for (uint8_t channel = 0; channel <= 0xF; channel++) {
943 if ((1<<channel) & mask) {
945 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
946 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
947 write_immediate_event (3, ev);
949 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
950 silence notes that came from another non-muted track. */
954 /* Resolve active notes. */
955 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
960 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
962 Track::monitoring_changed (self, gcd);
964 /* monitoring state changed, so flush out any on notes at the
968 PortSet& ports (_output->ports());
970 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
971 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
973 mp->require_resolve ();
977 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
980 md->reset_tracker ();
985 MidiTrack::monitoring_state () const
987 MonitorState ms = Track::monitoring_state();
988 if (ms == MonitoringSilence) {
989 return MonitoringInput;