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 #ifdef XXX_OLD_DESTRUCTIVE_API_XXX
143 if (Profile->get_trx()) {
144 _diskstream->set_destructive (false);
146 _diskstream->set_destructive (_mode == Destructive);
149 _diskstream->set_record_enabled (false);
151 _diskstream_data_recorded_connection.disconnect ();
152 mds->DataRecorded.connect_same_thread (
153 _diskstream_data_recorded_connection,
154 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
156 DiskstreamChanged (); /* EMIT SIGNAL */
159 boost::shared_ptr<MidiDiskstream>
160 MidiTrack::midi_diskstream() const
162 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
166 MidiTrack::set_state (const XMLNode& node, int version)
168 XMLProperty const * prop;
170 /* This must happen before Track::set_state(), as there will be a buffer
171 fill during that call, and we must fill buffers using the correct
174 if ((prop = node.property (X_("note-mode"))) != 0) {
175 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
177 _note_mode = Sustained;
180 if (Track::set_state (node, version)) {
184 // No destructive MIDI tracks (yet?)
187 if ((prop = node.property ("input-active")) != 0) {
188 set_input_active (string_is_affirmative (prop->value()));
191 ChannelMode playback_channel_mode = AllChannels;
192 ChannelMode capture_channel_mode = AllChannels;
194 if ((prop = node.property ("playback-channel-mode")) != 0) {
195 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
197 if ((prop = node.property ("capture-channel-mode")) != 0) {
198 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
200 if ((prop = node.property ("channel-mode")) != 0) {
201 /* 3.0 behaviour where capture and playback modes were not separated */
202 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
203 capture_channel_mode = playback_channel_mode;
206 unsigned int playback_channel_mask = 0xffff;
207 unsigned int capture_channel_mask = 0xffff;
209 if ((prop = node.property ("playback-channel-mask")) != 0) {
210 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
212 if ((prop = node.property ("capture-channel-mask")) != 0) {
213 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
215 if ((prop = node.property ("channel-mask")) != 0) {
216 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
217 capture_channel_mask = playback_channel_mask;
220 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
221 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
223 pending_state = const_cast<XMLNode*> (&node);
225 if (_session.state_of_the_state() & Session::Loading) {
226 _session.StateReady.connect_same_thread (
227 *this, boost::bind (&MidiTrack::set_state_part_two, this));
229 set_state_part_two ();
236 MidiTrack::state(bool full_state)
238 XMLNode& root (Track::state(full_state));
239 XMLNode* freeze_node;
242 if (_freeze_record.playlist) {
245 freeze_node = new XMLNode (X_("freeze-info"));
246 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
247 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
249 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
250 inode = new XMLNode (X_("processor"));
251 (*i)->id.print (buf, sizeof(buf));
252 inode->add_property (X_("id"), buf);
253 inode->add_child_copy ((*i)->state);
255 freeze_node->add_child_nocopy (*inode);
258 root.add_child_nocopy (*freeze_node);
261 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
262 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
263 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
264 root.add_property("playback-channel-mask", buf);
265 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
266 root.add_property("capture-channel-mask", buf);
268 root.add_property ("note-mode", enum_2_string (_note_mode));
269 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
270 root.add_property ("input-active", (_input_active ? "yes" : "no"));
272 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
273 if (boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) {
274 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c->second);
276 root.add_child_nocopy (ac->get_state ());
284 MidiTrack::set_state_part_two ()
287 XMLProperty const * prop;
290 /* This is called after all session state has been restored but before
291 have been made ports and connections are established.
294 if (pending_state == 0) {
298 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
300 _freeze_record.state = Frozen;
302 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
305 _freeze_record.processor_info.clear ();
307 if ((prop = fnode->property (X_("playlist"))) != 0) {
308 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
310 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
312 _freeze_record.playlist.reset();
313 _freeze_record.state = NoFreeze;
318 if ((prop = fnode->property (X_("state"))) != 0) {
319 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
322 XMLNodeConstIterator citer;
323 XMLNodeList clist = fnode->children();
325 for (citer = clist.begin(); citer != clist.end(); ++citer) {
326 if ((*citer)->name() != X_("processor")) {
330 if ((prop = (*citer)->property (X_("id"))) == 0) {
334 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
335 boost::shared_ptr<Processor>());
336 frii->id = prop->value ();
337 _freeze_record.processor_info.push_back (frii);
341 if (midi_diskstream ()) {
342 midi_diskstream()->set_block_size (_session.get_block_size ());
349 MidiTrack::restore_controls ()
351 // TODO order events (CC before PGM to set banks)
352 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
353 boost::shared_ptr<MidiTrack::MidiControl> mctrl = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second);
355 mctrl->restore_value();
361 MidiTrack::update_controls(const BufferSet& bufs)
363 const MidiBuffer& buf = bufs.get_midi(0);
364 for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
365 const Evoral::Event<framepos_t>& ev = *e;
366 const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
367 const boost::shared_ptr<Evoral::Control> control = this->control(param);
369 control->set_double(ev.value(), _session.transport_frame(), false);
374 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
378 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
380 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
382 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
383 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
384 if (can_internal_playback_seek(::llabs(playback_distance))) {
385 /* TODO should declick, and/or note-off */
386 internal_playback_seek(playback_distance);
391 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
393 if (n_outputs().n_total() == 0 && _processors.empty()) {
399 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
405 framepos_t transport_frame = _session.transport_frame();
408 framecnt_t playback_distance;
410 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
411 /* need to do this so that the diskstream sets its
412 playback distance to zero, thus causing diskstream::commit
415 BufferSet bufs; /* empty set - is OK, since nothing will happen */
417 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
418 need_butler = diskstream->commit (playback_distance);
422 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
424 fill_buffers_with_input (bufs, _input, nframes);
426 /* filter captured data before meter sees it */
427 _capture_filter.filter (bufs);
429 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
430 _meter->run (bufs, start_frame, end_frame, 1.0 /*speed()*/, nframes, true);
436 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
437 need_butler = diskstream->commit (playback_distance);
442 /* note diskstream uses our filter to filter/map playback channels appropriately. */
444 if (monitoring_state() == MonitoringInput) {
446 /* not actually recording, but we want to hear the input material anyway,
447 at least potentially (depending on monitoring options)
450 /* because the playback buffer is event based and not a
451 * continuous stream, we need to make sure that we empty
452 * it of events every cycle to avoid it filling up with events
453 * read from disk, while we are actually monitoring input
456 diskstream->flush_playback (start_frame, end_frame);
461 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
463 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
465 /* final argument: don't waste time with automation if we're not recording or rolling */
467 process_output_buffers (bufs, start_frame, end_frame, nframes,
468 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
470 flush_processor_buffers_locked (nframes);
472 need_butler = diskstream->commit (playback_distance);
478 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
480 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
482 if (ret == 0 && _step_editing) {
483 push_midi_input_to_step_edit_ringbuffer (nframes);
490 MidiTrack::realtime_locate ()
492 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
498 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
499 (*i)->realtime_locate ();
502 midi_diskstream()->reset_tracker ();
506 MidiTrack::realtime_handle_transport_stopped ()
508 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
514 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
515 (*i)->realtime_handle_transport_stopped ();
520 MidiTrack::non_realtime_locate (framepos_t pos)
522 Track::non_realtime_locate(pos);
524 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
529 /* Get the top unmuted region at this position. */
530 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
531 playlist->top_unmuted_region_at(pos));
536 /* the source may be missing, but the control still referenced in the GUI */
537 if (!region->midi_source() || !region->model()) {
541 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
546 /* Update track controllers based on its "automation". */
547 const framepos_t origin = region->position() - region->start();
548 BeatsFramesConverter bfc(_session.tempo_map(), origin);
549 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
550 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
551 boost::shared_ptr<Evoral::Control> rcontrol;
552 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
553 (rcontrol = region->control(tcontrol->parameter()))) {
554 const Evoral::Beats pos_beats = bfc.from(pos - origin);
555 if (rcontrol->list()->size() > 0) {
556 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
563 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
565 PortSet& ports (_input->ports());
567 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
569 Buffer& b (p->get_buffer (nframes));
570 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
573 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
575 const Evoral::Event<framepos_t> ev(*e, false);
577 /* note on, since for step edit, note length is determined
581 if (ev.is_note_on()) {
582 /* we don't care about the time for this purpose */
583 _step_edit_ring_buffer.write (0, ev.event_type(), ev.size(), ev.buffer());
590 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
592 MidiBuffer& buf (bufs.get_midi (0));
594 update_controls (bufs);
596 // Append immediate events
598 if (_immediate_events.read_space()) {
600 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
601 name(), _immediate_events.read_space()));
603 /* write as many of the immediate events as we can, but give "true" as
604 * the last argument ("stop on overflow in destination") so that we'll
605 * ship the rest out next time.
607 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
608 * possible position of the output buffer, so that we do not
609 * violate monotonicity when writing. Port::port_offset() will
610 * be non-zero if we're in a split process cycle.
612 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
617 MidiTrack::export_stuff (BufferSet& buffers,
620 boost::shared_ptr<Processor> endpoint,
621 bool include_endpoint,
625 if (buffers.count().n_midi() == 0) {
629 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
631 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
633 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
638 buffers.get_midi(0).clear();
639 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
643 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
648 boost::shared_ptr<Region>
649 MidiTrack::bounce (InterThreadInfo& itt)
651 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
654 boost::shared_ptr<Region>
655 MidiTrack::bounce_range (framepos_t start,
657 InterThreadInfo& itt,
658 boost::shared_ptr<Processor> endpoint,
659 bool include_endpoint)
661 vector<boost::shared_ptr<Source> > srcs;
662 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
666 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
668 std::cerr << "MIDI freeze currently unsupported" << std::endl;
672 MidiTrack::unfreeze ()
674 _freeze_record.state = UnFrozen;
675 FreezeChange (); /* EMIT SIGNAL */
679 MidiTrack::set_note_mode (NoteMode m)
682 midi_diskstream()->set_note_mode(m);
686 MidiTrack::describe_parameter (Evoral::Parameter param)
688 const std::string str(instrument_info().get_controller_name(param));
689 return str.empty() ? Automatable::describe_parameter(param) : str;
693 MidiTrack::midi_panic()
695 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
696 for (uint8_t channel = 0; channel <= 0xF; channel++) {
697 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
698 write_immediate_event(3, ev);
699 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
700 write_immediate_event(3, ev);
701 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
702 write_immediate_event(3, ev);
706 /** \return true on success, false on failure (no buffer space left)
709 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
711 if (!Evoral::midi_event_is_valid(buf, size)) {
712 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
715 return (_immediate_events.write (0, Evoral::MIDI_EVENT, size, buf) == size);
719 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
721 switch (param.type()) {
722 case MidiCCAutomation:
723 case MidiPgmChangeAutomation:
724 case MidiPitchBenderAutomation:
725 case MidiChannelPressureAutomation:
726 case MidiNotePressureAutomation:
727 case MidiSystemExclusiveAutomation:
728 /* The track control for MIDI parameters is for immediate events to act
729 as a control surface, write/touch for them is not currently
733 Automatable::set_parameter_automation_state(param, state);
738 MidiTrack::MidiControl::restore_value ()
740 actually_set_value (get_value(), Controllable::NoGroup);
744 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
746 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
747 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
750 if (isinf_local(val)) {
751 cerr << "MIDIControl value is infinity" << endl;
752 } else if (isnan_local(val)) {
753 cerr << "MIDIControl value is NaN" << endl;
754 } else if (val < desc.lower) {
755 cerr << "MIDIControl value is < " << desc.lower << endl;
756 } else if (val > desc.upper) {
757 cerr << "MIDIControl value is > " << desc.upper << endl;
766 assert(val <= desc.upper);
767 if ( ! _list || ! automation_playback()) {
769 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
770 switch(parameter.type()) {
771 case MidiCCAutomation:
772 ev[0] += MIDI_CMD_CONTROL;
773 ev[1] = parameter.id();
777 case MidiPgmChangeAutomation:
779 ev[0] += MIDI_CMD_PGM_CHANGE;
783 case MidiChannelPressureAutomation:
785 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
789 case MidiNotePressureAutomation:
790 ev[0] += MIDI_CMD_NOTE_PRESSURE;
791 ev[1] = parameter.id();
795 case MidiPitchBenderAutomation:
796 ev[0] += MIDI_CMD_BENDER;
797 ev[1] = 0x7F & int(val);
798 ev[2] = 0x7F & (int(val) >> 7);
804 _route->write_immediate_event(size, ev);
807 AutomationControl::actually_set_value(val, group_override);
811 MidiTrack::set_step_editing (bool yn)
813 if (_session.record_status() != Session::Disabled) {
817 if (yn != _step_editing) {
819 StepEditStatusChange (yn);
823 boost::shared_ptr<SMFSource>
824 MidiTrack::write_source (uint32_t)
826 return midi_diskstream()->write_source ();
830 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
832 if (_playback_filter.set_channel_mode(mode, mask)) {
833 _session.set_dirty();
838 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
840 if (_capture_filter.set_channel_mode(mode, mask)) {
841 _session.set_dirty();
846 MidiTrack::set_playback_channel_mask (uint16_t mask)
848 if (_playback_filter.set_channel_mask(mask)) {
849 _session.set_dirty();
854 MidiTrack::set_capture_channel_mask (uint16_t mask)
856 if (_capture_filter.set_channel_mask(mask)) {
857 _session.set_dirty();
861 boost::shared_ptr<MidiPlaylist>
862 MidiTrack::midi_playlist ()
864 return midi_diskstream()->midi_playlist ();
868 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
870 DataRecorded (src); /* EMIT SIGNAL */
874 MidiTrack::input_active () const
876 return _input_active;
880 MidiTrack::set_input_active (bool yn)
882 if (yn != _input_active) {
884 map_input_active (yn);
885 InputActiveChanged (); /* EMIT SIGNAL */
890 MidiTrack::map_input_active (bool yn)
896 PortSet& ports (_input->ports());
898 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
899 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
900 if (yn != mp->input_active()) {
901 mp->set_input_active (yn);
907 MidiTrack::track_input_active (IOChange change, void* /* src */)
909 if (change.type & IOChange::ConfigurationChanged) {
910 map_input_active (_input_active);
914 boost::shared_ptr<Diskstream>
915 MidiTrack::diskstream_factory (XMLNode const & node)
917 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
920 boost::shared_ptr<MidiBuffer>
921 MidiTrack::get_gui_feed_buffer () const
923 return midi_diskstream()->get_gui_feed_buffer ();
927 MidiTrack::act_on_mute ()
929 /* this is called right after our mute status has changed.
930 if we are now muted, send suitable output to shutdown
933 XXX we should should also stop all relevant note trackers.
936 /* If we haven't got a diskstream yet, there's nothing to worry about,
937 and we can't call get_channel_mask() anyway.
939 if (!midi_diskstream()) {
943 if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
944 /* only send messages for channels we are using */
946 uint16_t mask = _playback_filter.get_channel_mask();
948 for (uint8_t channel = 0; channel <= 0xF; channel++) {
950 if ((1<<channel) & mask) {
952 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
953 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
954 write_immediate_event (3, ev);
956 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
957 silence notes that came from another non-muted track. */
961 /* Resolve active notes. */
962 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
967 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
969 Track::monitoring_changed (self, gcd);
971 /* monitoring state changed, so flush out any on notes at the
975 PortSet& ports (_output->ports());
977 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
978 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
980 mp->require_resolve ();
984 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
987 md->reset_tracker ();
992 MidiTrack::monitoring_state () const
994 MonitorState ms = Track::monitoring_state();
995 if (ms == MonitoringSilence) {
996 return MonitoringInput;