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/parameter_types.h"
48 #include "ardour/port.h"
49 #include "ardour/processor.h"
50 #include "ardour/profile.h"
51 #include "ardour/session.h"
52 #include "ardour/session_playlists.h"
53 #include "ardour/utils.h"
58 class InterThreadInfo;
65 using namespace ARDOUR;
68 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
69 : Track (sess, name, flag, mode, DataType::MIDI)
70 , _immediate_events(1024) // FIXME: size?
71 , _step_edit_ring_buffer(64) // FIXME: size?
72 , _note_mode(Sustained)
73 , _step_editing (false)
74 , _input_active (true)
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_record_safe (bool yn, void *src)
118 if (_step_editing) { /* REQUIRES REVIEW */
122 Track::set_record_safe (yn, src);
126 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
128 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
129 and the diskstream must be set up to fill its buffers using the correct _note_mode.
131 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
132 mds->set_note_mode (_note_mode);
134 Track::set_diskstream (ds);
136 mds->reset_tracker ();
138 _diskstream->set_track (this);
139 if (Profile->get_trx()) {
140 _diskstream->set_destructive (false);
142 _diskstream->set_destructive (_mode == Destructive);
144 _diskstream->set_record_enabled (false);
146 _diskstream_data_recorded_connection.disconnect ();
147 mds->DataRecorded.connect_same_thread (
148 _diskstream_data_recorded_connection,
149 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
151 DiskstreamChanged (); /* EMIT SIGNAL */
154 boost::shared_ptr<MidiDiskstream>
155 MidiTrack::midi_diskstream() const
157 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
161 MidiTrack::set_state (const XMLNode& node, int version)
163 const XMLProperty *prop;
165 /* This must happen before Track::set_state(), as there will be a buffer
166 fill during that call, and we must fill buffers using the correct
169 if ((prop = node.property (X_("note-mode"))) != 0) {
170 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
172 _note_mode = Sustained;
175 if (Track::set_state (node, version)) {
179 // No destructive MIDI tracks (yet?)
182 if ((prop = node.property ("input-active")) != 0) {
183 set_input_active (string_is_affirmative (prop->value()));
186 ChannelMode playback_channel_mode = AllChannels;
187 ChannelMode capture_channel_mode = AllChannels;
189 if ((prop = node.property ("playback-channel-mode")) != 0) {
190 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
192 if ((prop = node.property ("capture-channel-mode")) != 0) {
193 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
195 if ((prop = node.property ("channel-mode")) != 0) {
196 /* 3.0 behaviour where capture and playback modes were not separated */
197 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
198 capture_channel_mode = playback_channel_mode;
201 unsigned int playback_channel_mask = 0xffff;
202 unsigned int capture_channel_mask = 0xffff;
204 if ((prop = node.property ("playback-channel-mask")) != 0) {
205 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
207 if ((prop = node.property ("capture-channel-mask")) != 0) {
208 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
210 if ((prop = node.property ("channel-mask")) != 0) {
211 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
212 capture_channel_mask = playback_channel_mask;
215 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
216 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
218 pending_state = const_cast<XMLNode*> (&node);
220 if (_session.state_of_the_state() & Session::Loading) {
221 _session.StateReady.connect_same_thread (
222 *this, boost::bind (&MidiTrack::set_state_part_two, this));
224 set_state_part_two ();
231 MidiTrack::state(bool full_state)
233 XMLNode& root (Track::state(full_state));
234 XMLNode* freeze_node;
237 if (_freeze_record.playlist) {
240 freeze_node = new XMLNode (X_("freeze-info"));
241 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
242 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
244 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
245 inode = new XMLNode (X_("processor"));
246 (*i)->id.print (buf, sizeof(buf));
247 inode->add_property (X_("id"), buf);
248 inode->add_child_copy ((*i)->state);
250 freeze_node->add_child_nocopy (*inode);
253 root.add_child_nocopy (*freeze_node);
256 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
257 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
258 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
259 root.add_property("playback-channel-mask", buf);
260 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
261 root.add_property("capture-channel-mask", buf);
263 root.add_property ("note-mode", enum_2_string (_note_mode));
264 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
265 root.add_property ("input-active", (_input_active ? "yes" : "no"));
271 MidiTrack::set_state_part_two ()
275 LocaleGuard lg (X_("C"));
277 /* This is called after all session state has been restored but before
278 have been made ports and connections are established.
281 if (pending_state == 0) {
285 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
287 _freeze_record.state = Frozen;
289 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
292 _freeze_record.processor_info.clear ();
294 if ((prop = fnode->property (X_("playlist"))) != 0) {
295 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
297 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
299 _freeze_record.playlist.reset();
300 _freeze_record.state = NoFreeze;
305 if ((prop = fnode->property (X_("state"))) != 0) {
306 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
309 XMLNodeConstIterator citer;
310 XMLNodeList clist = fnode->children();
312 for (citer = clist.begin(); citer != clist.end(); ++citer) {
313 if ((*citer)->name() != X_("processor")) {
317 if ((prop = (*citer)->property (X_("id"))) == 0) {
321 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
322 boost::shared_ptr<Processor>());
323 frii->id = prop->value ();
324 _freeze_record.processor_info.push_back (frii);
328 if (midi_diskstream ()) {
329 midi_diskstream()->set_block_size (_session.get_block_size ());
336 MidiTrack::update_controls(const BufferSet& bufs)
338 const MidiBuffer& buf = bufs.get_midi(0);
339 for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
340 const Evoral::MIDIEvent<framepos_t>& ev = *e;
341 const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
342 const boost::shared_ptr<Evoral::Control> control = this->control(param);
344 control->set_double(ev.value(), _session.transport_frame(), false);
349 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
353 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
355 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
357 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
358 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
359 if (can_internal_playback_seek(::llabs(playback_distance))) {
360 /* TODO should declick, and/or note-off */
361 internal_playback_seek(playback_distance);
366 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
368 if (n_outputs().n_total() == 0 && _processors.empty()) {
374 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
380 framepos_t transport_frame = _session.transport_frame();
383 framecnt_t playback_distance;
385 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
386 /* need to do this so that the diskstream sets its
387 playback distance to zero, thus causing diskstream::commit
390 BufferSet bufs; /* empty set - is OK, since nothing will happen */
392 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
393 need_butler = diskstream->commit (playback_distance);
397 if (_mute_control->list() && _mute_control->automation_playback()) {
399 const float mute = _mute_control->list()->rt_safe_eval(transport_frame, valid);
400 if (mute >= 0.5 && !muted()) {
401 _mute_control->set_value_unchecked(1.0); // mute
402 } else if (mute < 0.5 && muted()) {
403 _mute_control->set_value_unchecked(0.0); // unmute
407 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
409 fill_buffers_with_input (bufs, _input, nframes);
411 /* filter captured data before meter sees it */
412 _capture_filter.filter (bufs);
414 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
415 _meter->run (bufs, start_frame, end_frame, nframes, true);
421 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
422 need_butler = diskstream->commit (playback_distance);
427 /* note diskstream uses our filter to filter/map playback channels appropriately. */
429 if (monitoring_state() == MonitoringInput) {
431 /* not actually recording, but we want to hear the input material anyway,
432 at least potentially (depending on monitoring options)
435 /* because the playback buffer is event based and not a
436 * continuous stream, we need to make sure that we empty
437 * it of events every cycle to avoid it filling up with events
438 * read from disk, while we are actually monitoring input
441 diskstream->flush_playback (start_frame, end_frame);
446 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
448 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
450 /* final argument: don't waste time with automation if we're not recording or rolling */
452 process_output_buffers (bufs, start_frame, end_frame, nframes,
453 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
455 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
456 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
458 d->flush_buffers (nframes);
462 need_butler = diskstream->commit (playback_distance);
468 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
470 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
472 if (ret == 0 && _step_editing) {
473 push_midi_input_to_step_edit_ringbuffer (nframes);
480 MidiTrack::realtime_locate ()
482 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
488 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
489 (*i)->realtime_locate ();
492 midi_diskstream()->reset_tracker ();
496 MidiTrack::realtime_handle_transport_stopped ()
498 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
504 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
505 (*i)->realtime_handle_transport_stopped ();
510 MidiTrack::non_realtime_locate (framepos_t pos)
512 Track::non_realtime_locate(pos);
514 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
519 /* Get the top unmuted region at this position. */
520 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
521 playlist->top_unmuted_region_at(pos));
526 /* the source may be missing, but the control still referenced in the GUI */
527 if (!region->midi_source() || !region->model()) {
531 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
536 /* Update track controllers based on its "automation". */
537 const framepos_t origin = region->position() - region->start();
538 BeatsFramesConverter bfc(_session.tempo_map(), origin);
539 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
540 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
541 boost::shared_ptr<Evoral::Control> rcontrol;
542 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
543 (rcontrol = region->control(tcontrol->parameter()))) {
544 const Evoral::Beats pos_beats = bfc.from(pos - origin);
545 if (rcontrol->list()->size() > 0) {
546 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
553 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
555 PortSet& ports (_input->ports());
557 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
559 Buffer& b (p->get_buffer (nframes));
560 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
563 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
565 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
567 /* note on, since for step edit, note length is determined
571 if (ev.is_note_on()) {
572 /* we don't care about the time for this purpose */
573 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
580 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
582 MidiBuffer& buf (bufs.get_midi (0));
584 update_controls (bufs);
586 // Append immediate events
588 if (_immediate_events.read_space()) {
590 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
591 name(), _immediate_events.read_space()));
593 /* write as many of the immediate events as we can, but give "true" as
594 * the last argument ("stop on overflow in destination") so that we'll
595 * ship the rest out next time.
597 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
598 * possible position of the output buffer, so that we do not
599 * violate monotonicity when writing. Port::port_offset() will
600 * be non-zero if we're in a split process cycle.
602 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
607 MidiTrack::export_stuff (BufferSet& buffers,
610 boost::shared_ptr<Processor> endpoint,
611 bool include_endpoint,
615 if (buffers.count().n_midi() == 0) {
619 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
621 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
623 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
628 buffers.get_midi(0).clear();
629 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
633 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
638 boost::shared_ptr<Region>
639 MidiTrack::bounce (InterThreadInfo& itt)
641 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
644 boost::shared_ptr<Region>
645 MidiTrack::bounce_range (framepos_t start,
647 InterThreadInfo& itt,
648 boost::shared_ptr<Processor> endpoint,
649 bool include_endpoint)
651 vector<boost::shared_ptr<Source> > srcs;
652 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
656 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
658 std::cerr << "MIDI freeze currently unsupported" << std::endl;
662 MidiTrack::unfreeze ()
664 _freeze_record.state = UnFrozen;
665 FreezeChange (); /* EMIT SIGNAL */
669 MidiTrack::set_note_mode (NoteMode m)
672 midi_diskstream()->set_note_mode(m);
676 MidiTrack::describe_parameter (Evoral::Parameter param)
678 const std::string str(instrument_info().get_controller_name(param));
679 return str.empty() ? Automatable::describe_parameter(param) : str;
683 MidiTrack::midi_panic()
685 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
686 for (uint8_t channel = 0; channel <= 0xF; channel++) {
687 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
688 write_immediate_event(3, ev);
689 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
690 write_immediate_event(3, ev);
691 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
692 write_immediate_event(3, ev);
696 /** \return true on success, false on failure (no buffer space left)
699 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
701 if (!Evoral::midi_event_is_valid(buf, size)) {
702 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
705 const uint32_t type = midi_parameter_type(buf[0]);
706 return (_immediate_events.write (0, type, size, buf) == size);
710 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
712 switch (param.type()) {
713 case MidiCCAutomation:
714 case MidiPgmChangeAutomation:
715 case MidiPitchBenderAutomation:
716 case MidiChannelPressureAutomation:
717 case MidiSystemExclusiveAutomation:
718 /* The track control for MIDI parameters is for immediate events to act
719 as a control surface, write/touch for them is not currently
723 Automatable::set_parameter_automation_state(param, state);
728 MidiTrack::MidiControl::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
731 set_value_unchecked (val);
736 MidiTrack::MidiControl::set_value_unchecked(double val)
738 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
739 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
742 if (isinf_local(val)) {
743 cerr << "MIDIControl value is infinity" << endl;
744 } else if (isnan_local(val)) {
745 cerr << "MIDIControl value is NaN" << endl;
746 } else if (val < desc.lower) {
747 cerr << "MIDIControl value is < " << desc.lower << endl;
748 } else if (val > desc.upper) {
749 cerr << "MIDIControl value is > " << desc.upper << endl;
758 assert(val <= desc.upper);
759 if ( ! _list || ! automation_playback()) {
761 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
762 switch(parameter.type()) {
763 case MidiCCAutomation:
764 ev[0] += MIDI_CMD_CONTROL;
765 ev[1] = parameter.id();
769 case MidiPgmChangeAutomation:
771 ev[0] += MIDI_CMD_PGM_CHANGE;
775 case MidiChannelPressureAutomation:
777 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
781 case MidiPitchBenderAutomation:
782 ev[0] += MIDI_CMD_BENDER;
783 ev[1] = 0x7F & int(val);
784 ev[2] = 0x7F & (int(val) >> 7);
790 _route->write_immediate_event(size, ev);
793 AutomationControl::set_value(val, Controllable::NoGroup);
797 MidiTrack::set_step_editing (bool yn)
799 if (_session.record_status() != Session::Disabled) {
803 if (yn != _step_editing) {
805 StepEditStatusChange (yn);
809 boost::shared_ptr<SMFSource>
810 MidiTrack::write_source (uint32_t)
812 return midi_diskstream()->write_source ();
816 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
818 if (_playback_filter.set_channel_mode(mode, mask)) {
819 _session.set_dirty();
824 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
826 if (_capture_filter.set_channel_mode(mode, mask)) {
827 _session.set_dirty();
832 MidiTrack::set_playback_channel_mask (uint16_t mask)
834 if (_playback_filter.set_channel_mask(mask)) {
835 _session.set_dirty();
840 MidiTrack::set_capture_channel_mask (uint16_t mask)
842 if (_capture_filter.set_channel_mask(mask)) {
843 _session.set_dirty();
847 boost::shared_ptr<MidiPlaylist>
848 MidiTrack::midi_playlist ()
850 return midi_diskstream()->midi_playlist ();
854 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
856 DataRecorded (src); /* EMIT SIGNAL */
860 MidiTrack::input_active () const
862 return _input_active;
866 MidiTrack::set_input_active (bool yn)
868 if (yn != _input_active) {
870 map_input_active (yn);
871 InputActiveChanged (); /* EMIT SIGNAL */
876 MidiTrack::map_input_active (bool yn)
882 PortSet& ports (_input->ports());
884 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
885 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
886 if (yn != mp->input_active()) {
887 mp->set_input_active (yn);
893 MidiTrack::track_input_active (IOChange change, void* /* src */)
895 if (change.type & IOChange::ConfigurationChanged) {
896 map_input_active (_input_active);
900 boost::shared_ptr<Diskstream>
901 MidiTrack::diskstream_factory (XMLNode const & node)
903 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
906 boost::shared_ptr<MidiBuffer>
907 MidiTrack::get_gui_feed_buffer () const
909 return midi_diskstream()->get_gui_feed_buffer ();
913 MidiTrack::act_on_mute ()
915 /* this is called right after our mute status has changed.
916 if we are now muted, send suitable output to shutdown
919 XXX we should should also stop all relevant note trackers.
922 /* If we haven't got a diskstream yet, there's nothing to worry about,
923 and we can't call get_channel_mask() anyway.
925 if (!midi_diskstream()) {
929 if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) {
930 /* only send messages for channels we are using */
932 uint16_t mask = _playback_filter.get_channel_mask();
934 for (uint8_t channel = 0; channel <= 0xF; channel++) {
936 if ((1<<channel) & mask) {
938 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
939 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
940 write_immediate_event (3, ev);
942 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
943 silence notes that came from another non-muted track. */
947 /* Resolve active notes. */
948 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
953 MidiTrack::set_monitoring (MonitorChoice mc)
955 if (mc != _monitoring) {
957 Track::set_monitoring (mc);
959 /* monitoring state changed, so flush out any on notes at the
963 PortSet& ports (_output->ports());
965 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
966 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
968 mp->require_resolve ();
972 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
975 md->reset_tracker ();
981 MidiTrack::monitoring_state () const
983 MonitorState ms = Track::monitoring_state();
984 if (ms == MonitoringSilence) {
985 return MonitoringInput;