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 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
399 fill_buffers_with_input (bufs, _input, nframes);
401 /* filter captured data before meter sees it */
402 _capture_filter.filter (bufs);
404 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
405 _meter->run (bufs, start_frame, end_frame, nframes, true);
411 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
412 need_butler = diskstream->commit (playback_distance);
417 /* note diskstream uses our filter to filter/map playback channels appropriately. */
419 if (monitoring_state() == MonitoringInput) {
421 /* not actually recording, but we want to hear the input material anyway,
422 at least potentially (depending on monitoring options)
425 /* because the playback buffer is event based and not a
426 * continuous stream, we need to make sure that we empty
427 * it of events every cycle to avoid it filling up with events
428 * read from disk, while we are actually monitoring input
431 diskstream->flush_playback (start_frame, end_frame);
436 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
438 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
440 /* final argument: don't waste time with automation if we're not recording or rolling */
442 process_output_buffers (bufs, start_frame, end_frame, nframes,
443 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
445 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
446 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
448 d->flush_buffers (nframes);
452 need_butler = diskstream->commit (playback_distance);
458 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
460 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
462 if (ret == 0 && _step_editing) {
463 push_midi_input_to_step_edit_ringbuffer (nframes);
470 MidiTrack::realtime_locate ()
472 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
478 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
479 (*i)->realtime_locate ();
482 midi_diskstream()->reset_tracker ();
486 MidiTrack::realtime_handle_transport_stopped ()
488 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
494 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
495 (*i)->realtime_handle_transport_stopped ();
500 MidiTrack::non_realtime_locate (framepos_t pos)
502 Track::non_realtime_locate(pos);
504 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
509 /* Get the top unmuted region at this position. */
510 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
511 playlist->top_unmuted_region_at(pos));
516 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
521 /* Update track controllers based on its "automation". */
522 const framepos_t origin = region->position() - region->start();
523 BeatsFramesConverter bfc(_session.tempo_map(), origin);
524 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
525 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
526 boost::shared_ptr<Evoral::Control> rcontrol;
527 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
528 (rcontrol = region->control(tcontrol->parameter()))) {
529 const Evoral::Beats pos_beats = bfc.from(pos - origin);
530 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()));
536 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
538 PortSet& ports (_input->ports());
540 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
542 Buffer& b (p->get_buffer (nframes));
543 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
546 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
548 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
550 /* note on, since for step edit, note length is determined
554 if (ev.is_note_on()) {
555 /* we don't care about the time for this purpose */
556 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
563 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
565 MidiBuffer& buf (bufs.get_midi (0));
567 update_controls (bufs);
569 // Append immediate events
571 if (_immediate_events.read_space()) {
573 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
574 name(), _immediate_events.read_space()));
576 /* write as many of the immediate events as we can, but give "true" as
577 * the last argument ("stop on overflow in destination") so that we'll
578 * ship the rest out next time.
580 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
581 * possible position of the output buffer, so that we do not
582 * violate monotonicity when writing. Port::port_offset() will
583 * be non-zero if we're in a split process cycle.
585 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
590 MidiTrack::export_stuff (BufferSet& buffers,
593 boost::shared_ptr<Processor> endpoint,
594 bool include_endpoint,
598 if (buffers.count().n_midi() == 0) {
602 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
604 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
606 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
611 buffers.get_midi(0).clear();
612 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
616 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
621 boost::shared_ptr<Region>
622 MidiTrack::bounce (InterThreadInfo& itt)
624 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
627 boost::shared_ptr<Region>
628 MidiTrack::bounce_range (framepos_t start,
630 InterThreadInfo& itt,
631 boost::shared_ptr<Processor> endpoint,
632 bool include_endpoint)
634 vector<boost::shared_ptr<Source> > srcs;
635 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
639 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
641 std::cerr << "MIDI freeze currently unsupported" << std::endl;
645 MidiTrack::unfreeze ()
647 _freeze_record.state = UnFrozen;
648 FreezeChange (); /* EMIT SIGNAL */
652 MidiTrack::set_note_mode (NoteMode m)
655 midi_diskstream()->set_note_mode(m);
659 MidiTrack::describe_parameter (Evoral::Parameter param)
661 const std::string str(instrument_info().get_controller_name(param));
662 return str.empty() ? Automatable::describe_parameter(param) : str;
666 MidiTrack::midi_panic()
668 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
669 for (uint8_t channel = 0; channel <= 0xF; channel++) {
670 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
671 write_immediate_event(3, ev);
672 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
673 write_immediate_event(3, ev);
674 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
675 write_immediate_event(3, ev);
679 /** \return true on success, false on failure (no buffer space left)
682 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
684 if (!Evoral::midi_event_is_valid(buf, size)) {
685 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
688 const uint32_t type = midi_parameter_type(buf[0]);
689 return (_immediate_events.write (0, type, size, buf) == size);
693 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
695 switch (param.type()) {
696 case MidiCCAutomation:
697 case MidiPgmChangeAutomation:
698 case MidiPitchBenderAutomation:
699 case MidiChannelPressureAutomation:
700 case MidiSystemExclusiveAutomation:
701 /* The track control for MIDI parameters is for immediate events to act
702 as a control surface, write/touch for them is not currently
706 Automatable::set_parameter_automation_state(param, state);
711 MidiTrack::MidiControl::set_value(double val)
713 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
714 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
717 if (isinf_local(val)) {
718 cerr << "MIDIControl value is infinity" << endl;
719 } else if (isnan_local(val)) {
720 cerr << "MIDIControl value is NaN" << endl;
721 } else if (val < desc.lower) {
722 cerr << "MIDIControl value is < " << desc.lower << endl;
723 } else if (val > desc.upper) {
724 cerr << "MIDIControl value is > " << desc.upper << endl;
733 assert(val <= desc.upper);
734 if ( ! _list || ! automation_playback()) {
736 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
737 switch(parameter.type()) {
738 case MidiCCAutomation:
739 ev[0] += MIDI_CMD_CONTROL;
740 ev[1] = parameter.id();
744 case MidiPgmChangeAutomation:
746 ev[0] += MIDI_CMD_PGM_CHANGE;
750 case MidiChannelPressureAutomation:
752 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
756 case MidiPitchBenderAutomation:
757 ev[0] += MIDI_CMD_BENDER;
758 ev[1] = 0x7F & int(val);
759 ev[2] = 0x7F & (int(val) >> 7);
765 _route->write_immediate_event(size, ev);
768 AutomationControl::set_value(val);
772 MidiTrack::set_step_editing (bool yn)
774 if (_session.record_status() != Session::Disabled) {
778 if (yn != _step_editing) {
780 StepEditStatusChange (yn);
784 boost::shared_ptr<SMFSource>
785 MidiTrack::write_source (uint32_t)
787 return midi_diskstream()->write_source ();
791 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
793 if (_playback_filter.set_channel_mode(mode, mask)) {
794 _session.set_dirty();
799 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
801 if (_capture_filter.set_channel_mode(mode, mask)) {
802 _session.set_dirty();
807 MidiTrack::set_playback_channel_mask (uint16_t mask)
809 if (_playback_filter.set_channel_mask(mask)) {
810 _session.set_dirty();
815 MidiTrack::set_capture_channel_mask (uint16_t mask)
817 if (_capture_filter.set_channel_mask(mask)) {
818 _session.set_dirty();
822 boost::shared_ptr<MidiPlaylist>
823 MidiTrack::midi_playlist ()
825 return midi_diskstream()->midi_playlist ();
829 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
831 DataRecorded (src); /* EMIT SIGNAL */
835 MidiTrack::input_active () const
837 return _input_active;
841 MidiTrack::set_input_active (bool yn)
843 if (yn != _input_active) {
845 map_input_active (yn);
846 InputActiveChanged (); /* EMIT SIGNAL */
851 MidiTrack::map_input_active (bool yn)
857 PortSet& ports (_input->ports());
859 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
860 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
861 if (yn != mp->input_active()) {
862 mp->set_input_active (yn);
868 MidiTrack::track_input_active (IOChange change, void* /* src */)
870 if (change.type & IOChange::ConfigurationChanged) {
871 map_input_active (_input_active);
875 boost::shared_ptr<Diskstream>
876 MidiTrack::diskstream_factory (XMLNode const & node)
878 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
881 boost::shared_ptr<MidiBuffer>
882 MidiTrack::get_gui_feed_buffer () const
884 return midi_diskstream()->get_gui_feed_buffer ();
888 MidiTrack::act_on_mute ()
890 /* this is called right after our mute status has changed.
891 if we are now muted, send suitable output to shutdown
894 XXX we should should also stop all relevant note trackers.
897 /* If we haven't got a diskstream yet, there's nothing to worry about,
898 and we can't call get_channel_mask() anyway.
900 if (!midi_diskstream()) {
904 if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) {
905 /* only send messages for channels we are using */
907 uint16_t mask = _playback_filter.get_channel_mask();
909 for (uint8_t channel = 0; channel <= 0xF; channel++) {
911 if ((1<<channel) & mask) {
913 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
914 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
915 write_immediate_event (3, ev);
917 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
918 silence notes that came from another non-muted track. */
922 /* Resolve active notes. */
923 midi_diskstream()->resolve_tracker(_immediate_events, 0);
928 MidiTrack::set_monitoring (MonitorChoice mc)
930 if (mc != _monitoring) {
932 Track::set_monitoring (mc);
934 /* monitoring state changed, so flush out any on notes at the
938 PortSet& ports (_output->ports());
940 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
941 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
943 mp->require_resolve ();
947 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
950 md->reset_tracker ();
956 MidiTrack::monitoring_state () const
958 MonitorState ms = Track::monitoring_state();
959 if (ms == MonitoringSilence) {
960 return MonitoringInput;