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/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/utils.h"
60 class InterThreadInfo;
67 using namespace ARDOUR;
70 MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
71 : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
72 , _immediate_events(1024) // FIXME: size?
73 , _step_edit_ring_buffer(64) // FIXME: size?
74 , _note_mode(Sustained)
75 , _step_editing (false)
76 , _input_active (true)
80 MidiTrack::~MidiTrack ()
91 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
96 boost::shared_ptr<Diskstream>
97 MidiTrack::create_diskstream ()
99 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable);
101 assert(_mode != Destructive);
103 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
108 MidiTrack::can_be_record_safe ()
114 return Track::can_be_record_safe ();
118 MidiTrack::can_be_record_enabled ()
124 return Track::can_be_record_enabled ();
128 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
130 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
131 and the diskstream must be set up to fill its buffers using the correct _note_mode.
133 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
134 mds->set_note_mode (_note_mode);
136 Track::set_diskstream (ds);
138 mds->reset_tracker ();
140 _diskstream->set_track (this);
141 if (Profile->get_trx()) {
142 _diskstream->set_destructive (false);
144 _diskstream->set_destructive (_mode == Destructive);
146 _diskstream->set_record_enabled (false);
148 _diskstream_data_recorded_connection.disconnect ();
149 mds->DataRecorded.connect_same_thread (
150 _diskstream_data_recorded_connection,
151 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
153 DiskstreamChanged (); /* EMIT SIGNAL */
156 boost::shared_ptr<MidiDiskstream>
157 MidiTrack::midi_diskstream() const
159 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
163 MidiTrack::set_state (const XMLNode& node, int version)
165 XMLProperty const * prop;
167 /* This must happen before Track::set_state(), as there will be a buffer
168 fill during that call, and we must fill buffers using the correct
171 if ((prop = node.property (X_("note-mode"))) != 0) {
172 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
174 _note_mode = Sustained;
177 if (Track::set_state (node, version)) {
181 // No destructive MIDI tracks (yet?)
184 if ((prop = node.property ("input-active")) != 0) {
185 set_input_active (string_is_affirmative (prop->value()));
188 ChannelMode playback_channel_mode = AllChannels;
189 ChannelMode capture_channel_mode = AllChannels;
191 if ((prop = node.property ("playback-channel-mode")) != 0) {
192 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
194 if ((prop = node.property ("capture-channel-mode")) != 0) {
195 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
197 if ((prop = node.property ("channel-mode")) != 0) {
198 /* 3.0 behaviour where capture and playback modes were not separated */
199 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
200 capture_channel_mode = playback_channel_mode;
203 unsigned int playback_channel_mask = 0xffff;
204 unsigned int capture_channel_mask = 0xffff;
206 if ((prop = node.property ("playback-channel-mask")) != 0) {
207 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
209 if ((prop = node.property ("capture-channel-mask")) != 0) {
210 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
212 if ((prop = node.property ("channel-mask")) != 0) {
213 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
214 capture_channel_mask = playback_channel_mask;
217 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
218 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
220 pending_state = const_cast<XMLNode*> (&node);
222 if (_session.state_of_the_state() & Session::Loading) {
223 _session.StateReady.connect_same_thread (
224 *this, boost::bind (&MidiTrack::set_state_part_two, this));
226 set_state_part_two ();
233 MidiTrack::state(bool full_state)
235 XMLNode& root (Track::state(full_state));
236 XMLNode* freeze_node;
239 if (_freeze_record.playlist) {
242 freeze_node = new XMLNode (X_("freeze-info"));
243 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
244 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
246 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
247 inode = new XMLNode (X_("processor"));
248 (*i)->id.print (buf, sizeof(buf));
249 inode->add_property (X_("id"), buf);
250 inode->add_child_copy ((*i)->state);
252 freeze_node->add_child_nocopy (*inode);
255 root.add_child_nocopy (*freeze_node);
258 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
259 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
260 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
261 root.add_property("playback-channel-mask", buf);
262 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
263 root.add_property("capture-channel-mask", buf);
265 root.add_property ("note-mode", enum_2_string (_note_mode));
266 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
267 root.add_property ("input-active", (_input_active ? "yes" : "no"));
273 MidiTrack::set_state_part_two ()
276 XMLProperty const * prop;
279 /* This is called after all session state has been restored but before
280 have been made ports and connections are established.
283 if (pending_state == 0) {
287 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
289 _freeze_record.state = Frozen;
291 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
294 _freeze_record.processor_info.clear ();
296 if ((prop = fnode->property (X_("playlist"))) != 0) {
297 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
299 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
301 _freeze_record.playlist.reset();
302 _freeze_record.state = NoFreeze;
307 if ((prop = fnode->property (X_("state"))) != 0) {
308 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
311 XMLNodeConstIterator citer;
312 XMLNodeList clist = fnode->children();
314 for (citer = clist.begin(); citer != clist.end(); ++citer) {
315 if ((*citer)->name() != X_("processor")) {
319 if ((prop = (*citer)->property (X_("id"))) == 0) {
323 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
324 boost::shared_ptr<Processor>());
325 frii->id = prop->value ();
326 _freeze_record.processor_info.push_back (frii);
330 if (midi_diskstream ()) {
331 midi_diskstream()->set_block_size (_session.get_block_size ());
338 MidiTrack::update_controls(const BufferSet& bufs)
340 const MidiBuffer& buf = bufs.get_midi(0);
341 for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
342 const Evoral::MIDIEvent<framepos_t>& ev = *e;
343 const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
344 const boost::shared_ptr<Evoral::Control> control = this->control(param);
346 control->set_double(ev.value(), _session.transport_frame(), false);
351 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
355 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
357 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
359 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
360 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
361 if (can_internal_playback_seek(::llabs(playback_distance))) {
362 /* TODO should declick, and/or note-off */
363 internal_playback_seek(playback_distance);
368 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
370 if (n_outputs().n_total() == 0 && _processors.empty()) {
376 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
382 framepos_t transport_frame = _session.transport_frame();
385 framecnt_t playback_distance;
387 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
388 /* need to do this so that the diskstream sets its
389 playback distance to zero, thus causing diskstream::commit
392 BufferSet bufs; /* empty set - is OK, since nothing will happen */
394 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
395 need_butler = diskstream->commit (playback_distance);
399 if (_mute_control->list() && _mute_control->automation_playback()) {
401 const float mute = _mute_control->list()->rt_safe_eval(transport_frame, valid);
402 if (mute >= 0.5 && !muted()) {
403 _mute_control->set_value_unchecked(1.0); // mute
404 } else if (mute < 0.5 && muted()) {
405 _mute_control->set_value_unchecked(0.0); // unmute
409 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
411 fill_buffers_with_input (bufs, _input, nframes);
413 /* filter captured data before meter sees it */
414 _capture_filter.filter (bufs);
416 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
417 _meter->run (bufs, start_frame, end_frame, nframes, true);
423 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
424 need_butler = diskstream->commit (playback_distance);
429 /* note diskstream uses our filter to filter/map playback channels appropriately. */
431 if (monitoring_state() == MonitoringInput) {
433 /* not actually recording, but we want to hear the input material anyway,
434 at least potentially (depending on monitoring options)
437 /* because the playback buffer is event based and not a
438 * continuous stream, we need to make sure that we empty
439 * it of events every cycle to avoid it filling up with events
440 * read from disk, while we are actually monitoring input
443 diskstream->flush_playback (start_frame, end_frame);
448 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
450 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
452 /* final argument: don't waste time with automation if we're not recording or rolling */
454 process_output_buffers (bufs, start_frame, end_frame, nframes,
455 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
457 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
458 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
460 d->flush_buffers (nframes);
464 need_butler = diskstream->commit (playback_distance);
470 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
472 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
474 if (ret == 0 && _step_editing) {
475 push_midi_input_to_step_edit_ringbuffer (nframes);
482 MidiTrack::realtime_locate ()
484 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
490 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
491 (*i)->realtime_locate ();
494 midi_diskstream()->reset_tracker ();
498 MidiTrack::realtime_handle_transport_stopped ()
500 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
506 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
507 (*i)->realtime_handle_transport_stopped ();
512 MidiTrack::non_realtime_locate (framepos_t pos)
514 Track::non_realtime_locate(pos);
516 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
521 /* Get the top unmuted region at this position. */
522 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
523 playlist->top_unmuted_region_at(pos));
528 /* the source may be missing, but the control still referenced in the GUI */
529 if (!region->midi_source() || !region->model()) {
533 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
538 /* Update track controllers based on its "automation". */
539 const framepos_t origin = region->position() - region->start();
540 BeatsFramesConverter bfc(_session.tempo_map(), origin);
541 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
542 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
543 boost::shared_ptr<Evoral::Control> rcontrol;
544 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
545 (rcontrol = region->control(tcontrol->parameter()))) {
546 const Evoral::Beats pos_beats = bfc.from(pos - origin);
547 if (rcontrol->list()->size() > 0) {
548 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
555 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
557 PortSet& ports (_input->ports());
559 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
561 Buffer& b (p->get_buffer (nframes));
562 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
565 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
567 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
569 /* note on, since for step edit, note length is determined
573 if (ev.is_note_on()) {
574 /* we don't care about the time for this purpose */
575 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
582 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
584 MidiBuffer& buf (bufs.get_midi (0));
586 update_controls (bufs);
588 // Append immediate events
590 if (_immediate_events.read_space()) {
592 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
593 name(), _immediate_events.read_space()));
595 /* write as many of the immediate events as we can, but give "true" as
596 * the last argument ("stop on overflow in destination") so that we'll
597 * ship the rest out next time.
599 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
600 * possible position of the output buffer, so that we do not
601 * violate monotonicity when writing. Port::port_offset() will
602 * be non-zero if we're in a split process cycle.
604 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
609 MidiTrack::export_stuff (BufferSet& buffers,
612 boost::shared_ptr<Processor> endpoint,
613 bool include_endpoint,
617 if (buffers.count().n_midi() == 0) {
621 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
623 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
625 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
630 buffers.get_midi(0).clear();
631 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
635 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
640 boost::shared_ptr<Region>
641 MidiTrack::bounce (InterThreadInfo& itt)
643 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
646 boost::shared_ptr<Region>
647 MidiTrack::bounce_range (framepos_t start,
649 InterThreadInfo& itt,
650 boost::shared_ptr<Processor> endpoint,
651 bool include_endpoint)
653 vector<boost::shared_ptr<Source> > srcs;
654 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
658 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
660 std::cerr << "MIDI freeze currently unsupported" << std::endl;
664 MidiTrack::unfreeze ()
666 _freeze_record.state = UnFrozen;
667 FreezeChange (); /* EMIT SIGNAL */
671 MidiTrack::set_note_mode (NoteMode m)
674 midi_diskstream()->set_note_mode(m);
678 MidiTrack::describe_parameter (Evoral::Parameter param)
680 const std::string str(instrument_info().get_controller_name(param));
681 return str.empty() ? Automatable::describe_parameter(param) : str;
685 MidiTrack::midi_panic()
687 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
688 for (uint8_t channel = 0; channel <= 0xF; channel++) {
689 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
690 write_immediate_event(3, ev);
691 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
692 write_immediate_event(3, ev);
693 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
694 write_immediate_event(3, ev);
698 /** \return true on success, false on failure (no buffer space left)
701 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
703 if (!Evoral::midi_event_is_valid(buf, size)) {
704 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
707 const uint32_t type = midi_parameter_type(buf[0]);
708 return (_immediate_events.write (0, type, 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 MidiSystemExclusiveAutomation:
720 /* The track control for MIDI parameters is for immediate events to act
721 as a control surface, write/touch for them is not currently
725 Automatable::set_parameter_automation_state(param, state);
730 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
732 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
733 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
736 if (isinf_local(val)) {
737 cerr << "MIDIControl value is infinity" << endl;
738 } else if (isnan_local(val)) {
739 cerr << "MIDIControl value is NaN" << endl;
740 } else if (val < desc.lower) {
741 cerr << "MIDIControl value is < " << desc.lower << endl;
742 } else if (val > desc.upper) {
743 cerr << "MIDIControl value is > " << desc.upper << endl;
752 assert(val <= desc.upper);
753 if ( ! _list || ! automation_playback()) {
755 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
756 switch(parameter.type()) {
757 case MidiCCAutomation:
758 ev[0] += MIDI_CMD_CONTROL;
759 ev[1] = parameter.id();
763 case MidiPgmChangeAutomation:
765 ev[0] += MIDI_CMD_PGM_CHANGE;
769 case MidiChannelPressureAutomation:
771 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
775 case MidiPitchBenderAutomation:
776 ev[0] += MIDI_CMD_BENDER;
777 ev[1] = 0x7F & int(val);
778 ev[2] = 0x7F & (int(val) >> 7);
784 _route->write_immediate_event(size, ev);
787 AutomationControl::actually_set_value(val, group_override);
791 MidiTrack::set_step_editing (bool yn)
793 if (_session.record_status() != Session::Disabled) {
797 if (yn != _step_editing) {
799 StepEditStatusChange (yn);
803 boost::shared_ptr<SMFSource>
804 MidiTrack::write_source (uint32_t)
806 return midi_diskstream()->write_source ();
810 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
812 if (_playback_filter.set_channel_mode(mode, mask)) {
813 _session.set_dirty();
818 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
820 if (_capture_filter.set_channel_mode(mode, mask)) {
821 _session.set_dirty();
826 MidiTrack::set_playback_channel_mask (uint16_t mask)
828 if (_playback_filter.set_channel_mask(mask)) {
829 _session.set_dirty();
834 MidiTrack::set_capture_channel_mask (uint16_t mask)
836 if (_capture_filter.set_channel_mask(mask)) {
837 _session.set_dirty();
841 boost::shared_ptr<MidiPlaylist>
842 MidiTrack::midi_playlist ()
844 return midi_diskstream()->midi_playlist ();
848 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
850 DataRecorded (src); /* EMIT SIGNAL */
854 MidiTrack::input_active () const
856 return _input_active;
860 MidiTrack::set_input_active (bool yn)
862 if (yn != _input_active) {
864 map_input_active (yn);
865 InputActiveChanged (); /* EMIT SIGNAL */
870 MidiTrack::map_input_active (bool yn)
876 PortSet& ports (_input->ports());
878 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
879 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
880 if (yn != mp->input_active()) {
881 mp->set_input_active (yn);
887 MidiTrack::track_input_active (IOChange change, void* /* src */)
889 if (change.type & IOChange::ConfigurationChanged) {
890 map_input_active (_input_active);
894 boost::shared_ptr<Diskstream>
895 MidiTrack::diskstream_factory (XMLNode const & node)
897 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
900 boost::shared_ptr<MidiBuffer>
901 MidiTrack::get_gui_feed_buffer () const
903 return midi_diskstream()->get_gui_feed_buffer ();
907 MidiTrack::act_on_mute ()
909 /* this is called right after our mute status has changed.
910 if we are now muted, send suitable output to shutdown
913 XXX we should should also stop all relevant note trackers.
916 /* If we haven't got a diskstream yet, there's nothing to worry about,
917 and we can't call get_channel_mask() anyway.
919 if (!midi_diskstream()) {
923 if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
924 /* only send messages for channels we are using */
926 uint16_t mask = _playback_filter.get_channel_mask();
928 for (uint8_t channel = 0; channel <= 0xF; channel++) {
930 if ((1<<channel) & mask) {
932 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
933 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
934 write_immediate_event (3, ev);
936 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
937 silence notes that came from another non-muted track. */
941 /* Resolve active notes. */
942 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
947 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
949 Track::monitoring_changed (self, gcd);
951 /* monitoring state changed, so flush out any on notes at the
955 PortSet& ports (_output->ports());
957 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
958 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
960 mp->require_resolve ();
964 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
967 md->reset_tracker ();
972 MidiTrack::monitoring_state () const
974 MonitorState ms = Track::monitoring_state();
975 if (ms == MonitoringSilence) {
976 return MonitoringInput;