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(6096) // FIXME: size?
73 , _step_edit_ring_buffer(64) // FIXME: size?
74 , _note_mode(Sustained)
75 , _step_editing (false)
76 , _input_active (true)
78 _session.SessionLoaded.connect_same_thread (*this, boost::bind (&MidiTrack::restore_controls, this));
81 MidiTrack::~MidiTrack ()
92 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
97 boost::shared_ptr<Diskstream>
98 MidiTrack::create_diskstream ()
100 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable);
102 assert(_mode != Destructive);
104 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
109 MidiTrack::can_be_record_safe ()
115 return Track::can_be_record_safe ();
119 MidiTrack::can_be_record_enabled ()
125 return Track::can_be_record_enabled ();
129 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
131 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
132 and the diskstream must be set up to fill its buffers using the correct _note_mode.
134 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
135 mds->set_note_mode (_note_mode);
137 Track::set_diskstream (ds);
139 mds->reset_tracker ();
141 _diskstream->set_track (this);
142 if (Profile->get_trx()) {
143 _diskstream->set_destructive (false);
145 _diskstream->set_destructive (_mode == Destructive);
147 _diskstream->set_record_enabled (false);
149 _diskstream_data_recorded_connection.disconnect ();
150 mds->DataRecorded.connect_same_thread (
151 _diskstream_data_recorded_connection,
152 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
154 DiskstreamChanged (); /* EMIT SIGNAL */
157 boost::shared_ptr<MidiDiskstream>
158 MidiTrack::midi_diskstream() const
160 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
164 MidiTrack::set_state (const XMLNode& node, int version)
166 XMLProperty const * prop;
168 /* This must happen before Track::set_state(), as there will be a buffer
169 fill during that call, and we must fill buffers using the correct
172 if ((prop = node.property (X_("note-mode"))) != 0) {
173 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
175 _note_mode = Sustained;
178 if (Track::set_state (node, version)) {
182 // No destructive MIDI tracks (yet?)
185 if ((prop = node.property ("input-active")) != 0) {
186 set_input_active (string_is_affirmative (prop->value()));
189 ChannelMode playback_channel_mode = AllChannels;
190 ChannelMode capture_channel_mode = AllChannels;
192 if ((prop = node.property ("playback-channel-mode")) != 0) {
193 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
195 if ((prop = node.property ("capture-channel-mode")) != 0) {
196 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
198 if ((prop = node.property ("channel-mode")) != 0) {
199 /* 3.0 behaviour where capture and playback modes were not separated */
200 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
201 capture_channel_mode = playback_channel_mode;
204 unsigned int playback_channel_mask = 0xffff;
205 unsigned int capture_channel_mask = 0xffff;
207 if ((prop = node.property ("playback-channel-mask")) != 0) {
208 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
210 if ((prop = node.property ("capture-channel-mask")) != 0) {
211 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
213 if ((prop = node.property ("channel-mask")) != 0) {
214 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
215 capture_channel_mask = playback_channel_mask;
218 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
219 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
221 pending_state = const_cast<XMLNode*> (&node);
223 if (_session.state_of_the_state() & Session::Loading) {
224 _session.StateReady.connect_same_thread (
225 *this, boost::bind (&MidiTrack::set_state_part_two, this));
227 set_state_part_two ();
234 MidiTrack::state(bool full_state)
236 XMLNode& root (Track::state(full_state));
237 XMLNode* freeze_node;
240 if (_freeze_record.playlist) {
243 freeze_node = new XMLNode (X_("freeze-info"));
244 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
245 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
247 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
248 inode = new XMLNode (X_("processor"));
249 (*i)->id.print (buf, sizeof(buf));
250 inode->add_property (X_("id"), buf);
251 inode->add_child_copy ((*i)->state);
253 freeze_node->add_child_nocopy (*inode);
256 root.add_child_nocopy (*freeze_node);
259 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
260 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
261 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
262 root.add_property("playback-channel-mask", buf);
263 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
264 root.add_property("capture-channel-mask", buf);
266 root.add_property ("note-mode", enum_2_string (_note_mode));
267 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
268 root.add_property ("input-active", (_input_active ? "yes" : "no"));
270 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
271 if (boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) {
272 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c->second);
274 root.add_child_nocopy (ac->get_state ());
282 MidiTrack::set_state_part_two ()
285 XMLProperty const * prop;
288 /* This is called after all session state has been restored but before
289 have been made ports and connections are established.
292 if (pending_state == 0) {
296 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
298 _freeze_record.state = Frozen;
300 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
303 _freeze_record.processor_info.clear ();
305 if ((prop = fnode->property (X_("playlist"))) != 0) {
306 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
308 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
310 _freeze_record.playlist.reset();
311 _freeze_record.state = NoFreeze;
316 if ((prop = fnode->property (X_("state"))) != 0) {
317 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
320 XMLNodeConstIterator citer;
321 XMLNodeList clist = fnode->children();
323 for (citer = clist.begin(); citer != clist.end(); ++citer) {
324 if ((*citer)->name() != X_("processor")) {
328 if ((prop = (*citer)->property (X_("id"))) == 0) {
332 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
333 boost::shared_ptr<Processor>());
334 frii->id = prop->value ();
335 _freeze_record.processor_info.push_back (frii);
339 if (midi_diskstream ()) {
340 midi_diskstream()->set_block_size (_session.get_block_size ());
347 MidiTrack::restore_controls ()
349 // TODO order events (CC before PGM to set banks)
350 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
351 boost::shared_ptr<MidiTrack::MidiControl> mctrl = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second);
353 mctrl->restore_value();
359 MidiTrack::update_controls(const BufferSet& bufs)
361 const MidiBuffer& buf = bufs.get_midi(0);
362 for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
363 const Evoral::Event<framepos_t>& ev = *e;
364 const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
365 const boost::shared_ptr<Evoral::Control> control = this->control(param);
367 control->set_double(ev.value(), _session.transport_frame(), false);
372 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
376 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
378 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
380 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
381 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
382 if (can_internal_playback_seek(::llabs(playback_distance))) {
383 /* TODO should declick, and/or note-off */
384 internal_playback_seek(playback_distance);
389 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
391 if (n_outputs().n_total() == 0 && _processors.empty()) {
397 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
403 framepos_t transport_frame = _session.transport_frame();
406 framecnt_t playback_distance;
408 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
409 /* need to do this so that the diskstream sets its
410 playback distance to zero, thus causing diskstream::commit
413 BufferSet bufs; /* empty set - is OK, since nothing will happen */
415 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
416 need_butler = diskstream->commit (playback_distance);
420 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
422 fill_buffers_with_input (bufs, _input, nframes);
424 /* filter captured data before meter sees it */
425 _capture_filter.filter (bufs);
427 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
428 _meter->run (bufs, start_frame, end_frame, 1.0 /*speed()*/, nframes, true);
434 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
435 need_butler = diskstream->commit (playback_distance);
440 /* note diskstream uses our filter to filter/map playback channels appropriately. */
442 if (monitoring_state() == MonitoringInput) {
444 /* not actually recording, but we want to hear the input material anyway,
445 at least potentially (depending on monitoring options)
448 /* because the playback buffer is event based and not a
449 * continuous stream, we need to make sure that we empty
450 * it of events every cycle to avoid it filling up with events
451 * read from disk, while we are actually monitoring input
454 diskstream->flush_playback (start_frame, end_frame);
459 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
461 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
463 /* final argument: don't waste time with automation if we're not recording or rolling */
465 process_output_buffers (bufs, start_frame, end_frame, nframes,
466 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
468 flush_processor_buffers_locked (nframes);
470 need_butler = diskstream->commit (playback_distance);
476 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
478 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
480 if (ret == 0 && _step_editing) {
481 push_midi_input_to_step_edit_ringbuffer (nframes);
488 MidiTrack::realtime_locate ()
490 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
496 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
497 (*i)->realtime_locate ();
500 midi_diskstream()->reset_tracker ();
504 MidiTrack::realtime_handle_transport_stopped ()
506 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
512 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
513 (*i)->realtime_handle_transport_stopped ();
518 MidiTrack::non_realtime_locate (framepos_t pos)
520 Track::non_realtime_locate(pos);
522 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
527 /* Get the top unmuted region at this position. */
528 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
529 playlist->top_unmuted_region_at(pos));
534 /* the source may be missing, but the control still referenced in the GUI */
535 if (!region->midi_source() || !region->model()) {
539 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
544 /* Update track controllers based on its "automation". */
545 const framepos_t origin = region->position() - region->start();
546 BeatsFramesConverter bfc(_session.tempo_map(), origin);
547 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
548 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
549 boost::shared_ptr<Evoral::Control> rcontrol;
550 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
551 (rcontrol = region->control(tcontrol->parameter()))) {
552 const Evoral::Beats pos_beats = bfc.from(pos - origin);
553 if (rcontrol->list()->size() > 0) {
554 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
561 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
563 PortSet& ports (_input->ports());
565 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
567 Buffer& b (p->get_buffer (nframes));
568 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
571 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
573 const Evoral::Event<framepos_t> ev(*e, false);
575 /* note on, since for step edit, note length is determined
579 if (ev.is_note_on()) {
580 /* we don't care about the time for this purpose */
581 _step_edit_ring_buffer.write (0, ev.event_type(), ev.size(), ev.buffer());
588 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
590 MidiBuffer& buf (bufs.get_midi (0));
592 update_controls (bufs);
594 // Append immediate events
596 if (_immediate_events.read_space()) {
598 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
599 name(), _immediate_events.read_space()));
601 /* write as many of the immediate events as we can, but give "true" as
602 * the last argument ("stop on overflow in destination") so that we'll
603 * ship the rest out next time.
605 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
606 * possible position of the output buffer, so that we do not
607 * violate monotonicity when writing. Port::port_offset() will
608 * be non-zero if we're in a split process cycle.
610 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
615 MidiTrack::export_stuff (BufferSet& buffers,
618 boost::shared_ptr<Processor> endpoint,
619 bool include_endpoint,
623 if (buffers.count().n_midi() == 0) {
627 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
629 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
631 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
636 buffers.get_midi(0).clear();
637 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
641 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
646 boost::shared_ptr<Region>
647 MidiTrack::bounce (InterThreadInfo& itt)
649 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
652 boost::shared_ptr<Region>
653 MidiTrack::bounce_range (framepos_t start,
655 InterThreadInfo& itt,
656 boost::shared_ptr<Processor> endpoint,
657 bool include_endpoint)
659 vector<boost::shared_ptr<Source> > srcs;
660 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
664 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
666 std::cerr << "MIDI freeze currently unsupported" << std::endl;
670 MidiTrack::unfreeze ()
672 _freeze_record.state = UnFrozen;
673 FreezeChange (); /* EMIT SIGNAL */
677 MidiTrack::set_note_mode (NoteMode m)
680 midi_diskstream()->set_note_mode(m);
684 MidiTrack::describe_parameter (Evoral::Parameter param)
686 const std::string str(instrument_info().get_controller_name(param));
687 return str.empty() ? Automatable::describe_parameter(param) : str;
691 MidiTrack::midi_panic()
693 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
694 for (uint8_t channel = 0; channel <= 0xF; channel++) {
695 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
696 write_immediate_event(3, ev);
697 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
698 write_immediate_event(3, ev);
699 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
700 write_immediate_event(3, ev);
704 /** \return true on success, false on failure (no buffer space left)
707 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
709 if (!Evoral::midi_event_is_valid(buf, size)) {
710 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
713 return (_immediate_events.write (0, Evoral::MIDI_EVENT, size, buf) == size);
717 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
719 switch (param.type()) {
720 case MidiCCAutomation:
721 case MidiPgmChangeAutomation:
722 case MidiPitchBenderAutomation:
723 case MidiChannelPressureAutomation:
724 case MidiNotePressureAutomation:
725 case MidiSystemExclusiveAutomation:
726 /* The track control for MIDI parameters is for immediate events to act
727 as a control surface, write/touch for them is not currently
731 Automatable::set_parameter_automation_state(param, state);
736 MidiTrack::MidiControl::restore_value ()
738 actually_set_value (get_value(), Controllable::NoGroup);
742 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
744 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
745 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
748 if (isinf_local(val)) {
749 cerr << "MIDIControl value is infinity" << endl;
750 } else if (isnan_local(val)) {
751 cerr << "MIDIControl value is NaN" << endl;
752 } else if (val < desc.lower) {
753 cerr << "MIDIControl value is < " << desc.lower << endl;
754 } else if (val > desc.upper) {
755 cerr << "MIDIControl value is > " << desc.upper << endl;
764 assert(val <= desc.upper);
765 if ( ! _list || ! automation_playback()) {
767 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
768 switch(parameter.type()) {
769 case MidiCCAutomation:
770 ev[0] += MIDI_CMD_CONTROL;
771 ev[1] = parameter.id();
775 case MidiPgmChangeAutomation:
777 ev[0] += MIDI_CMD_PGM_CHANGE;
781 case MidiChannelPressureAutomation:
783 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
787 case MidiNotePressureAutomation:
788 ev[0] += MIDI_CMD_NOTE_PRESSURE;
789 ev[1] = parameter.id();
793 case MidiPitchBenderAutomation:
794 ev[0] += MIDI_CMD_BENDER;
795 ev[1] = 0x7F & int(val);
796 ev[2] = 0x7F & (int(val) >> 7);
802 _route->write_immediate_event(size, ev);
805 AutomationControl::actually_set_value(val, group_override);
809 MidiTrack::set_step_editing (bool yn)
811 if (_session.record_status() != Session::Disabled) {
815 if (yn != _step_editing) {
817 StepEditStatusChange (yn);
821 boost::shared_ptr<SMFSource>
822 MidiTrack::write_source (uint32_t)
824 return midi_diskstream()->write_source ();
828 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
830 if (_playback_filter.set_channel_mode(mode, mask)) {
831 _session.set_dirty();
836 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
838 if (_capture_filter.set_channel_mode(mode, mask)) {
839 _session.set_dirty();
844 MidiTrack::set_playback_channel_mask (uint16_t mask)
846 if (_playback_filter.set_channel_mask(mask)) {
847 _session.set_dirty();
852 MidiTrack::set_capture_channel_mask (uint16_t mask)
854 if (_capture_filter.set_channel_mask(mask)) {
855 _session.set_dirty();
859 boost::shared_ptr<MidiPlaylist>
860 MidiTrack::midi_playlist ()
862 return midi_diskstream()->midi_playlist ();
866 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
868 DataRecorded (src); /* EMIT SIGNAL */
872 MidiTrack::input_active () const
874 return _input_active;
878 MidiTrack::set_input_active (bool yn)
880 if (yn != _input_active) {
882 map_input_active (yn);
883 InputActiveChanged (); /* EMIT SIGNAL */
888 MidiTrack::map_input_active (bool yn)
894 PortSet& ports (_input->ports());
896 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
897 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
898 if (yn != mp->input_active()) {
899 mp->set_input_active (yn);
905 MidiTrack::track_input_active (IOChange change, void* /* src */)
907 if (change.type & IOChange::ConfigurationChanged) {
908 map_input_active (_input_active);
912 boost::shared_ptr<Diskstream>
913 MidiTrack::diskstream_factory (XMLNode const & node)
915 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
918 boost::shared_ptr<MidiBuffer>
919 MidiTrack::get_gui_feed_buffer () const
921 return midi_diskstream()->get_gui_feed_buffer ();
925 MidiTrack::act_on_mute ()
927 /* this is called right after our mute status has changed.
928 if we are now muted, send suitable output to shutdown
931 XXX we should should also stop all relevant note trackers.
934 /* If we haven't got a diskstream yet, there's nothing to worry about,
935 and we can't call get_channel_mask() anyway.
937 if (!midi_diskstream()) {
941 if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
942 /* only send messages for channels we are using */
944 uint16_t mask = _playback_filter.get_channel_mask();
946 for (uint8_t channel = 0; channel <= 0xF; channel++) {
948 if ((1<<channel) & mask) {
950 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
951 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
952 write_immediate_event (3, ev);
954 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
955 silence notes that came from another non-muted track. */
959 /* Resolve active notes. */
960 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
965 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
967 Track::monitoring_changed (self, gcd);
969 /* monitoring state changed, so flush out any on notes at the
973 PortSet& ports (_output->ports());
975 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
976 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
978 mp->require_resolve ();
982 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
985 md->reset_tracker ();
990 MidiTrack::monitoring_state () const
992 MonitorState ms = Track::monitoring_state();
993 if (ms == MonitoringSilence) {
994 return MonitoringInput;