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 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
401 fill_buffers_with_input (bufs, _input, nframes);
403 /* filter captured data before meter sees it */
404 _capture_filter.filter (bufs);
406 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
407 _meter->run (bufs, start_frame, end_frame, 1.0 /*speed()*/, nframes, true);
413 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
414 need_butler = diskstream->commit (playback_distance);
419 /* note diskstream uses our filter to filter/map playback channels appropriately. */
421 if (monitoring_state() == MonitoringInput) {
423 /* not actually recording, but we want to hear the input material anyway,
424 at least potentially (depending on monitoring options)
427 /* because the playback buffer is event based and not a
428 * continuous stream, we need to make sure that we empty
429 * it of events every cycle to avoid it filling up with events
430 * read from disk, while we are actually monitoring input
433 diskstream->flush_playback (start_frame, end_frame);
438 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
440 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
442 /* final argument: don't waste time with automation if we're not recording or rolling */
444 process_output_buffers (bufs, start_frame, end_frame, nframes,
445 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
447 flush_processor_buffers_locked (nframes);
449 need_butler = diskstream->commit (playback_distance);
455 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
457 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
459 if (ret == 0 && _step_editing) {
460 push_midi_input_to_step_edit_ringbuffer (nframes);
467 MidiTrack::realtime_locate ()
469 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
475 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
476 (*i)->realtime_locate ();
479 midi_diskstream()->reset_tracker ();
483 MidiTrack::realtime_handle_transport_stopped ()
485 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
491 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
492 (*i)->realtime_handle_transport_stopped ();
497 MidiTrack::non_realtime_locate (framepos_t pos)
499 Track::non_realtime_locate(pos);
501 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
506 /* Get the top unmuted region at this position. */
507 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
508 playlist->top_unmuted_region_at(pos));
513 /* the source may be missing, but the control still referenced in the GUI */
514 if (!region->midi_source() || !region->model()) {
518 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
523 /* Update track controllers based on its "automation". */
524 const framepos_t origin = region->position() - region->start();
525 BeatsFramesConverter bfc(_session.tempo_map(), origin);
526 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
527 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
528 boost::shared_ptr<Evoral::Control> rcontrol;
529 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
530 (rcontrol = region->control(tcontrol->parameter()))) {
531 const Evoral::Beats pos_beats = bfc.from(pos - origin);
532 if (rcontrol->list()->size() > 0) {
533 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
540 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
542 PortSet& ports (_input->ports());
544 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
546 Buffer& b (p->get_buffer (nframes));
547 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
550 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
552 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
554 /* note on, since for step edit, note length is determined
558 if (ev.is_note_on()) {
559 /* we don't care about the time for this purpose */
560 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
567 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
569 MidiBuffer& buf (bufs.get_midi (0));
571 update_controls (bufs);
573 // Append immediate events
575 if (_immediate_events.read_space()) {
577 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
578 name(), _immediate_events.read_space()));
580 /* write as many of the immediate events as we can, but give "true" as
581 * the last argument ("stop on overflow in destination") so that we'll
582 * ship the rest out next time.
584 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
585 * possible position of the output buffer, so that we do not
586 * violate monotonicity when writing. Port::port_offset() will
587 * be non-zero if we're in a split process cycle.
589 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
594 MidiTrack::export_stuff (BufferSet& buffers,
597 boost::shared_ptr<Processor> endpoint,
598 bool include_endpoint,
602 if (buffers.count().n_midi() == 0) {
606 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
608 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
610 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
615 buffers.get_midi(0).clear();
616 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
620 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
625 boost::shared_ptr<Region>
626 MidiTrack::bounce (InterThreadInfo& itt)
628 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
631 boost::shared_ptr<Region>
632 MidiTrack::bounce_range (framepos_t start,
634 InterThreadInfo& itt,
635 boost::shared_ptr<Processor> endpoint,
636 bool include_endpoint)
638 vector<boost::shared_ptr<Source> > srcs;
639 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
643 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
645 std::cerr << "MIDI freeze currently unsupported" << std::endl;
649 MidiTrack::unfreeze ()
651 _freeze_record.state = UnFrozen;
652 FreezeChange (); /* EMIT SIGNAL */
656 MidiTrack::set_note_mode (NoteMode m)
659 midi_diskstream()->set_note_mode(m);
663 MidiTrack::describe_parameter (Evoral::Parameter param)
665 const std::string str(instrument_info().get_controller_name(param));
666 return str.empty() ? Automatable::describe_parameter(param) : str;
670 MidiTrack::midi_panic()
672 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
673 for (uint8_t channel = 0; channel <= 0xF; channel++) {
674 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
675 write_immediate_event(3, ev);
676 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
677 write_immediate_event(3, ev);
678 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
679 write_immediate_event(3, ev);
683 /** \return true on success, false on failure (no buffer space left)
686 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
688 if (!Evoral::midi_event_is_valid(buf, size)) {
689 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
692 const uint32_t type = midi_parameter_type(buf[0]);
693 return (_immediate_events.write (0, type, size, buf) == size);
697 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
699 switch (param.type()) {
700 case MidiCCAutomation:
701 case MidiPgmChangeAutomation:
702 case MidiPitchBenderAutomation:
703 case MidiChannelPressureAutomation:
704 case MidiSystemExclusiveAutomation:
705 /* The track control for MIDI parameters is for immediate events to act
706 as a control surface, write/touch for them is not currently
710 Automatable::set_parameter_automation_state(param, state);
715 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
717 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
718 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
721 if (isinf_local(val)) {
722 cerr << "MIDIControl value is infinity" << endl;
723 } else if (isnan_local(val)) {
724 cerr << "MIDIControl value is NaN" << endl;
725 } else if (val < desc.lower) {
726 cerr << "MIDIControl value is < " << desc.lower << endl;
727 } else if (val > desc.upper) {
728 cerr << "MIDIControl value is > " << desc.upper << endl;
737 assert(val <= desc.upper);
738 if ( ! _list || ! automation_playback()) {
740 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
741 switch(parameter.type()) {
742 case MidiCCAutomation:
743 ev[0] += MIDI_CMD_CONTROL;
744 ev[1] = parameter.id();
748 case MidiPgmChangeAutomation:
750 ev[0] += MIDI_CMD_PGM_CHANGE;
754 case MidiChannelPressureAutomation:
756 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
760 case MidiPitchBenderAutomation:
761 ev[0] += MIDI_CMD_BENDER;
762 ev[1] = 0x7F & int(val);
763 ev[2] = 0x7F & (int(val) >> 7);
769 _route->write_immediate_event(size, ev);
772 AutomationControl::actually_set_value(val, group_override);
776 MidiTrack::set_step_editing (bool yn)
778 if (_session.record_status() != Session::Disabled) {
782 if (yn != _step_editing) {
784 StepEditStatusChange (yn);
788 boost::shared_ptr<SMFSource>
789 MidiTrack::write_source (uint32_t)
791 return midi_diskstream()->write_source ();
795 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
797 if (_playback_filter.set_channel_mode(mode, mask)) {
798 _session.set_dirty();
803 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
805 if (_capture_filter.set_channel_mode(mode, mask)) {
806 _session.set_dirty();
811 MidiTrack::set_playback_channel_mask (uint16_t mask)
813 if (_playback_filter.set_channel_mask(mask)) {
814 _session.set_dirty();
819 MidiTrack::set_capture_channel_mask (uint16_t mask)
821 if (_capture_filter.set_channel_mask(mask)) {
822 _session.set_dirty();
826 boost::shared_ptr<MidiPlaylist>
827 MidiTrack::midi_playlist ()
829 return midi_diskstream()->midi_playlist ();
833 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
835 DataRecorded (src); /* EMIT SIGNAL */
839 MidiTrack::input_active () const
841 return _input_active;
845 MidiTrack::set_input_active (bool yn)
847 if (yn != _input_active) {
849 map_input_active (yn);
850 InputActiveChanged (); /* EMIT SIGNAL */
855 MidiTrack::map_input_active (bool yn)
861 PortSet& ports (_input->ports());
863 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
864 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
865 if (yn != mp->input_active()) {
866 mp->set_input_active (yn);
872 MidiTrack::track_input_active (IOChange change, void* /* src */)
874 if (change.type & IOChange::ConfigurationChanged) {
875 map_input_active (_input_active);
879 boost::shared_ptr<Diskstream>
880 MidiTrack::diskstream_factory (XMLNode const & node)
882 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
885 boost::shared_ptr<MidiBuffer>
886 MidiTrack::get_gui_feed_buffer () const
888 return midi_diskstream()->get_gui_feed_buffer ();
892 MidiTrack::act_on_mute ()
894 /* this is called right after our mute status has changed.
895 if we are now muted, send suitable output to shutdown
898 XXX we should should also stop all relevant note trackers.
901 /* If we haven't got a diskstream yet, there's nothing to worry about,
902 and we can't call get_channel_mask() anyway.
904 if (!midi_diskstream()) {
908 if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
909 /* only send messages for channels we are using */
911 uint16_t mask = _playback_filter.get_channel_mask();
913 for (uint8_t channel = 0; channel <= 0xF; channel++) {
915 if ((1<<channel) & mask) {
917 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
918 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
919 write_immediate_event (3, ev);
921 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
922 silence notes that came from another non-muted track. */
926 /* Resolve active notes. */
927 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
932 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
934 Track::monitoring_changed (self, gcd);
936 /* monitoring state changed, so flush out any on notes at the
940 PortSet& ports (_output->ports());
942 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
943 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
945 mp->require_resolve ();
949 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
952 md->reset_tracker ();
957 MidiTrack::monitoring_state () const
959 MonitorState ms = Track::monitoring_state();
960 if (ms == MonitoringSilence) {
961 return MonitoringInput;