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 if (rcontrol->list()->size() > 0) {
531 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()));
538 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
540 PortSet& ports (_input->ports());
542 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
544 Buffer& b (p->get_buffer (nframes));
545 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
548 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
550 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
552 /* note on, since for step edit, note length is determined
556 if (ev.is_note_on()) {
557 /* we don't care about the time for this purpose */
558 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
565 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
567 MidiBuffer& buf (bufs.get_midi (0));
569 update_controls (bufs);
571 // Append immediate events
573 if (_immediate_events.read_space()) {
575 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
576 name(), _immediate_events.read_space()));
578 /* write as many of the immediate events as we can, but give "true" as
579 * the last argument ("stop on overflow in destination") so that we'll
580 * ship the rest out next time.
582 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
583 * possible position of the output buffer, so that we do not
584 * violate monotonicity when writing. Port::port_offset() will
585 * be non-zero if we're in a split process cycle.
587 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
592 MidiTrack::export_stuff (BufferSet& buffers,
595 boost::shared_ptr<Processor> endpoint,
596 bool include_endpoint,
600 if (buffers.count().n_midi() == 0) {
604 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
606 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
608 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
613 buffers.get_midi(0).clear();
614 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
618 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
623 boost::shared_ptr<Region>
624 MidiTrack::bounce (InterThreadInfo& itt)
626 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
629 boost::shared_ptr<Region>
630 MidiTrack::bounce_range (framepos_t start,
632 InterThreadInfo& itt,
633 boost::shared_ptr<Processor> endpoint,
634 bool include_endpoint)
636 vector<boost::shared_ptr<Source> > srcs;
637 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
641 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
643 std::cerr << "MIDI freeze currently unsupported" << std::endl;
647 MidiTrack::unfreeze ()
649 _freeze_record.state = UnFrozen;
650 FreezeChange (); /* EMIT SIGNAL */
654 MidiTrack::set_note_mode (NoteMode m)
657 midi_diskstream()->set_note_mode(m);
661 MidiTrack::describe_parameter (Evoral::Parameter param)
663 const std::string str(instrument_info().get_controller_name(param));
664 return str.empty() ? Automatable::describe_parameter(param) : str;
668 MidiTrack::midi_panic()
670 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
671 for (uint8_t channel = 0; channel <= 0xF; channel++) {
672 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
673 write_immediate_event(3, ev);
674 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
675 write_immediate_event(3, ev);
676 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
677 write_immediate_event(3, ev);
681 /** \return true on success, false on failure (no buffer space left)
684 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
686 if (!Evoral::midi_event_is_valid(buf, size)) {
687 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
690 const uint32_t type = midi_parameter_type(buf[0]);
691 return (_immediate_events.write (0, type, size, buf) == size);
695 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
697 switch (param.type()) {
698 case MidiCCAutomation:
699 case MidiPgmChangeAutomation:
700 case MidiPitchBenderAutomation:
701 case MidiChannelPressureAutomation:
702 case MidiSystemExclusiveAutomation:
703 /* The track control for MIDI parameters is for immediate events to act
704 as a control surface, write/touch for them is not currently
708 Automatable::set_parameter_automation_state(param, state);
713 MidiTrack::MidiControl::set_value(double val)
715 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
716 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
719 if (isinf_local(val)) {
720 cerr << "MIDIControl value is infinity" << endl;
721 } else if (isnan_local(val)) {
722 cerr << "MIDIControl value is NaN" << endl;
723 } else if (val < desc.lower) {
724 cerr << "MIDIControl value is < " << desc.lower << endl;
725 } else if (val > desc.upper) {
726 cerr << "MIDIControl value is > " << desc.upper << endl;
735 assert(val <= desc.upper);
736 if ( ! _list || ! automation_playback()) {
738 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
739 switch(parameter.type()) {
740 case MidiCCAutomation:
741 ev[0] += MIDI_CMD_CONTROL;
742 ev[1] = parameter.id();
746 case MidiPgmChangeAutomation:
748 ev[0] += MIDI_CMD_PGM_CHANGE;
752 case MidiChannelPressureAutomation:
754 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
758 case MidiPitchBenderAutomation:
759 ev[0] += MIDI_CMD_BENDER;
760 ev[1] = 0x7F & int(val);
761 ev[2] = 0x7F & (int(val) >> 7);
767 _route->write_immediate_event(size, ev);
770 AutomationControl::set_value(val);
774 MidiTrack::set_step_editing (bool yn)
776 if (_session.record_status() != Session::Disabled) {
780 if (yn != _step_editing) {
782 StepEditStatusChange (yn);
786 boost::shared_ptr<SMFSource>
787 MidiTrack::write_source (uint32_t)
789 return midi_diskstream()->write_source ();
793 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
795 if (_playback_filter.set_channel_mode(mode, mask)) {
796 _session.set_dirty();
801 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
803 if (_capture_filter.set_channel_mode(mode, mask)) {
804 _session.set_dirty();
809 MidiTrack::set_playback_channel_mask (uint16_t mask)
811 if (_playback_filter.set_channel_mask(mask)) {
812 _session.set_dirty();
817 MidiTrack::set_capture_channel_mask (uint16_t mask)
819 if (_capture_filter.set_channel_mask(mask)) {
820 _session.set_dirty();
824 boost::shared_ptr<MidiPlaylist>
825 MidiTrack::midi_playlist ()
827 return midi_diskstream()->midi_playlist ();
831 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
833 DataRecorded (src); /* EMIT SIGNAL */
837 MidiTrack::input_active () const
839 return _input_active;
843 MidiTrack::set_input_active (bool yn)
845 if (yn != _input_active) {
847 map_input_active (yn);
848 InputActiveChanged (); /* EMIT SIGNAL */
853 MidiTrack::map_input_active (bool yn)
859 PortSet& ports (_input->ports());
861 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
862 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
863 if (yn != mp->input_active()) {
864 mp->set_input_active (yn);
870 MidiTrack::track_input_active (IOChange change, void* /* src */)
872 if (change.type & IOChange::ConfigurationChanged) {
873 map_input_active (_input_active);
877 boost::shared_ptr<Diskstream>
878 MidiTrack::diskstream_factory (XMLNode const & node)
880 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
883 boost::shared_ptr<MidiBuffer>
884 MidiTrack::get_gui_feed_buffer () const
886 return midi_diskstream()->get_gui_feed_buffer ();
890 MidiTrack::act_on_mute ()
892 /* this is called right after our mute status has changed.
893 if we are now muted, send suitable output to shutdown
896 XXX we should should also stop all relevant note trackers.
899 /* If we haven't got a diskstream yet, there's nothing to worry about,
900 and we can't call get_channel_mask() anyway.
902 if (!midi_diskstream()) {
906 if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) {
907 /* only send messages for channels we are using */
909 uint16_t mask = _playback_filter.get_channel_mask();
911 for (uint8_t channel = 0; channel <= 0xF; channel++) {
913 if ((1<<channel) & mask) {
915 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
916 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
917 write_immediate_event (3, ev);
919 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
920 silence notes that came from another non-muted track. */
924 /* Resolve active notes. */
925 midi_diskstream()->resolve_tracker(_immediate_events, 0);
930 MidiTrack::set_monitoring (MonitorChoice mc)
932 if (mc != _monitoring) {
934 Track::set_monitoring (mc);
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 ();
958 MidiTrack::monitoring_state () const
960 MonitorState ms = Track::monitoring_state();
961 if (ms == MonitoringSilence) {
962 return MonitoringInput;