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 /* the source may be missing, but the control still referenced in the GUI */
517 if (!region->midi_source() || !region->model()) {
521 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
526 /* Update track controllers based on its "automation". */
527 const framepos_t origin = region->position() - region->start();
528 BeatsFramesConverter bfc(_session.tempo_map(), origin);
529 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
530 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
531 boost::shared_ptr<Evoral::Control> rcontrol;
532 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
533 (rcontrol = region->control(tcontrol->parameter()))) {
534 const Evoral::Beats pos_beats = bfc.from(pos - origin);
535 if (rcontrol->list()->size() > 0) {
536 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()));
543 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
545 PortSet& ports (_input->ports());
547 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
549 Buffer& b (p->get_buffer (nframes));
550 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
553 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
555 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
557 /* note on, since for step edit, note length is determined
561 if (ev.is_note_on()) {
562 /* we don't care about the time for this purpose */
563 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
570 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
572 MidiBuffer& buf (bufs.get_midi (0));
574 update_controls (bufs);
576 // Append immediate events
578 if (_immediate_events.read_space()) {
580 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
581 name(), _immediate_events.read_space()));
583 /* write as many of the immediate events as we can, but give "true" as
584 * the last argument ("stop on overflow in destination") so that we'll
585 * ship the rest out next time.
587 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
588 * possible position of the output buffer, so that we do not
589 * violate monotonicity when writing. Port::port_offset() will
590 * be non-zero if we're in a split process cycle.
592 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
597 MidiTrack::export_stuff (BufferSet& buffers,
600 boost::shared_ptr<Processor> endpoint,
601 bool include_endpoint,
605 if (buffers.count().n_midi() == 0) {
609 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
611 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
613 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
618 buffers.get_midi(0).clear();
619 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
623 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
628 boost::shared_ptr<Region>
629 MidiTrack::bounce (InterThreadInfo& itt)
631 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
634 boost::shared_ptr<Region>
635 MidiTrack::bounce_range (framepos_t start,
637 InterThreadInfo& itt,
638 boost::shared_ptr<Processor> endpoint,
639 bool include_endpoint)
641 vector<boost::shared_ptr<Source> > srcs;
642 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
646 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
648 std::cerr << "MIDI freeze currently unsupported" << std::endl;
652 MidiTrack::unfreeze ()
654 _freeze_record.state = UnFrozen;
655 FreezeChange (); /* EMIT SIGNAL */
659 MidiTrack::set_note_mode (NoteMode m)
662 midi_diskstream()->set_note_mode(m);
666 MidiTrack::describe_parameter (Evoral::Parameter param)
668 const std::string str(instrument_info().get_controller_name(param));
669 return str.empty() ? Automatable::describe_parameter(param) : str;
673 MidiTrack::midi_panic()
675 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
676 for (uint8_t channel = 0; channel <= 0xF; channel++) {
677 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
678 write_immediate_event(3, ev);
679 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
680 write_immediate_event(3, ev);
681 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
682 write_immediate_event(3, ev);
686 /** \return true on success, false on failure (no buffer space left)
689 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
691 if (!Evoral::midi_event_is_valid(buf, size)) {
692 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
695 const uint32_t type = midi_parameter_type(buf[0]);
696 return (_immediate_events.write (0, type, size, buf) == size);
700 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
702 switch (param.type()) {
703 case MidiCCAutomation:
704 case MidiPgmChangeAutomation:
705 case MidiPitchBenderAutomation:
706 case MidiChannelPressureAutomation:
707 case MidiSystemExclusiveAutomation:
708 /* The track control for MIDI parameters is for immediate events to act
709 as a control surface, write/touch for them is not currently
713 Automatable::set_parameter_automation_state(param, state);
718 MidiTrack::MidiControl::set_value(double val)
720 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
721 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
724 if (isinf_local(val)) {
725 cerr << "MIDIControl value is infinity" << endl;
726 } else if (isnan_local(val)) {
727 cerr << "MIDIControl value is NaN" << endl;
728 } else if (val < desc.lower) {
729 cerr << "MIDIControl value is < " << desc.lower << endl;
730 } else if (val > desc.upper) {
731 cerr << "MIDIControl value is > " << desc.upper << endl;
740 assert(val <= desc.upper);
741 if ( ! _list || ! automation_playback()) {
743 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
744 switch(parameter.type()) {
745 case MidiCCAutomation:
746 ev[0] += MIDI_CMD_CONTROL;
747 ev[1] = parameter.id();
751 case MidiPgmChangeAutomation:
753 ev[0] += MIDI_CMD_PGM_CHANGE;
757 case MidiChannelPressureAutomation:
759 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
763 case MidiPitchBenderAutomation:
764 ev[0] += MIDI_CMD_BENDER;
765 ev[1] = 0x7F & int(val);
766 ev[2] = 0x7F & (int(val) >> 7);
772 _route->write_immediate_event(size, ev);
775 AutomationControl::set_value(val);
779 MidiTrack::set_step_editing (bool yn)
781 if (_session.record_status() != Session::Disabled) {
785 if (yn != _step_editing) {
787 StepEditStatusChange (yn);
791 boost::shared_ptr<SMFSource>
792 MidiTrack::write_source (uint32_t)
794 return midi_diskstream()->write_source ();
798 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
800 if (_playback_filter.set_channel_mode(mode, mask)) {
801 _session.set_dirty();
806 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
808 if (_capture_filter.set_channel_mode(mode, mask)) {
809 _session.set_dirty();
814 MidiTrack::set_playback_channel_mask (uint16_t mask)
816 if (_playback_filter.set_channel_mask(mask)) {
817 _session.set_dirty();
822 MidiTrack::set_capture_channel_mask (uint16_t mask)
824 if (_capture_filter.set_channel_mask(mask)) {
825 _session.set_dirty();
829 boost::shared_ptr<MidiPlaylist>
830 MidiTrack::midi_playlist ()
832 return midi_diskstream()->midi_playlist ();
836 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
838 DataRecorded (src); /* EMIT SIGNAL */
842 MidiTrack::input_active () const
844 return _input_active;
848 MidiTrack::set_input_active (bool yn)
850 if (yn != _input_active) {
852 map_input_active (yn);
853 InputActiveChanged (); /* EMIT SIGNAL */
858 MidiTrack::map_input_active (bool yn)
864 PortSet& ports (_input->ports());
866 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
867 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
868 if (yn != mp->input_active()) {
869 mp->set_input_active (yn);
875 MidiTrack::track_input_active (IOChange change, void* /* src */)
877 if (change.type & IOChange::ConfigurationChanged) {
878 map_input_active (_input_active);
882 boost::shared_ptr<Diskstream>
883 MidiTrack::diskstream_factory (XMLNode const & node)
885 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
888 boost::shared_ptr<MidiBuffer>
889 MidiTrack::get_gui_feed_buffer () const
891 return midi_diskstream()->get_gui_feed_buffer ();
895 MidiTrack::act_on_mute ()
897 /* this is called right after our mute status has changed.
898 if we are now muted, send suitable output to shutdown
901 XXX we should should also stop all relevant note trackers.
904 /* If we haven't got a diskstream yet, there's nothing to worry about,
905 and we can't call get_channel_mask() anyway.
907 if (!midi_diskstream()) {
911 if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) {
912 /* only send messages for channels we are using */
914 uint16_t mask = _playback_filter.get_channel_mask();
916 for (uint8_t channel = 0; channel <= 0xF; channel++) {
918 if ((1<<channel) & mask) {
920 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
921 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
922 write_immediate_event (3, ev);
924 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
925 silence notes that came from another non-muted track. */
929 /* Resolve active notes. */
930 midi_diskstream()->resolve_tracker(_immediate_events, 0);
935 MidiTrack::set_monitoring (MonitorChoice mc)
937 if (mc != _monitoring) {
939 Track::set_monitoring (mc);
941 /* monitoring state changed, so flush out any on notes at the
945 PortSet& ports (_output->ports());
947 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
948 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
950 mp->require_resolve ();
954 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
957 md->reset_tracker ();
963 MidiTrack::monitoring_state () const
965 MonitorState ms = Track::monitoring_state();
966 if (ms == MonitoringSilence) {
967 return MonitoringInput;