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, Controllable::GroupControlDisposition group_override)
112 Track::set_record_enabled (yn, group_override);
116 MidiTrack::set_record_safe (bool yn, Controllable::GroupControlDisposition group_override)
118 if (_step_editing) { /* REQUIRES REVIEW */
122 Track::set_record_safe (yn, group_override);
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 if (_mute_control->list() && _mute_control->automation_playback()) {
399 const float mute = _mute_control->list()->rt_safe_eval(transport_frame, valid);
400 if (mute >= 0.5 && !muted()) {
401 _mute_control->set_value_unchecked(1.0); // mute
402 } else if (mute < 0.5 && muted()) {
403 _mute_control->set_value_unchecked(0.0); // unmute
407 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
409 fill_buffers_with_input (bufs, _input, nframes);
411 /* filter captured data before meter sees it */
412 _capture_filter.filter (bufs);
414 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
415 _meter->run (bufs, start_frame, end_frame, nframes, true);
421 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
422 need_butler = diskstream->commit (playback_distance);
427 /* note diskstream uses our filter to filter/map playback channels appropriately. */
429 if (monitoring_state() == MonitoringInput) {
431 /* not actually recording, but we want to hear the input material anyway,
432 at least potentially (depending on monitoring options)
435 /* because the playback buffer is event based and not a
436 * continuous stream, we need to make sure that we empty
437 * it of events every cycle to avoid it filling up with events
438 * read from disk, while we are actually monitoring input
441 diskstream->flush_playback (start_frame, end_frame);
446 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
448 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
450 /* final argument: don't waste time with automation if we're not recording or rolling */
452 process_output_buffers (bufs, start_frame, end_frame, nframes,
453 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
455 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
456 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
458 d->flush_buffers (nframes);
462 need_butler = diskstream->commit (playback_distance);
468 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
470 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
472 if (ret == 0 && _step_editing) {
473 push_midi_input_to_step_edit_ringbuffer (nframes);
480 MidiTrack::realtime_locate ()
482 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
488 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
489 (*i)->realtime_locate ();
492 midi_diskstream()->reset_tracker ();
496 MidiTrack::realtime_handle_transport_stopped ()
498 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
504 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
505 (*i)->realtime_handle_transport_stopped ();
510 MidiTrack::non_realtime_locate (framepos_t pos)
512 Track::non_realtime_locate(pos);
514 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
519 /* Get the top unmuted region at this position. */
520 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
521 playlist->top_unmuted_region_at(pos));
526 /* the source may be missing, but the control still referenced in the GUI */
527 if (!region->midi_source() || !region->model()) {
531 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
536 /* Update track controllers based on its "automation". */
537 const framepos_t origin = region->position() - region->start();
538 BeatsFramesConverter bfc(_session.tempo_map(), origin);
539 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
540 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
541 boost::shared_ptr<Evoral::Control> rcontrol;
542 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
543 (rcontrol = region->control(tcontrol->parameter()))) {
544 const Evoral::Beats pos_beats = bfc.from(pos - origin);
545 if (rcontrol->list()->size() > 0) {
546 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
553 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
555 PortSet& ports (_input->ports());
557 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
559 Buffer& b (p->get_buffer (nframes));
560 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
563 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
565 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
567 /* note on, since for step edit, note length is determined
571 if (ev.is_note_on()) {
572 /* we don't care about the time for this purpose */
573 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
580 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
582 MidiBuffer& buf (bufs.get_midi (0));
584 update_controls (bufs);
586 // Append immediate events
588 if (_immediate_events.read_space()) {
590 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
591 name(), _immediate_events.read_space()));
593 /* write as many of the immediate events as we can, but give "true" as
594 * the last argument ("stop on overflow in destination") so that we'll
595 * ship the rest out next time.
597 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
598 * possible position of the output buffer, so that we do not
599 * violate monotonicity when writing. Port::port_offset() will
600 * be non-zero if we're in a split process cycle.
602 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
607 MidiTrack::export_stuff (BufferSet& buffers,
610 boost::shared_ptr<Processor> endpoint,
611 bool include_endpoint,
615 if (buffers.count().n_midi() == 0) {
619 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
621 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
623 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
628 buffers.get_midi(0).clear();
629 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
633 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
638 boost::shared_ptr<Region>
639 MidiTrack::bounce (InterThreadInfo& itt)
641 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
644 boost::shared_ptr<Region>
645 MidiTrack::bounce_range (framepos_t start,
647 InterThreadInfo& itt,
648 boost::shared_ptr<Processor> endpoint,
649 bool include_endpoint)
651 vector<boost::shared_ptr<Source> > srcs;
652 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
656 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
658 std::cerr << "MIDI freeze currently unsupported" << std::endl;
662 MidiTrack::unfreeze ()
664 _freeze_record.state = UnFrozen;
665 FreezeChange (); /* EMIT SIGNAL */
669 MidiTrack::set_note_mode (NoteMode m)
672 midi_diskstream()->set_note_mode(m);
676 MidiTrack::describe_parameter (Evoral::Parameter param)
678 const std::string str(instrument_info().get_controller_name(param));
679 return str.empty() ? Automatable::describe_parameter(param) : str;
683 MidiTrack::midi_panic()
685 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
686 for (uint8_t channel = 0; channel <= 0xF; channel++) {
687 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
688 write_immediate_event(3, ev);
689 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
690 write_immediate_event(3, ev);
691 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
692 write_immediate_event(3, ev);
696 /** \return true on success, false on failure (no buffer space left)
699 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
701 if (!Evoral::midi_event_is_valid(buf, size)) {
702 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
705 const uint32_t type = midi_parameter_type(buf[0]);
706 return (_immediate_events.write (0, type, size, buf) == size);
710 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
712 switch (param.type()) {
713 case MidiCCAutomation:
714 case MidiPgmChangeAutomation:
715 case MidiPitchBenderAutomation:
716 case MidiChannelPressureAutomation:
717 case MidiSystemExclusiveAutomation:
718 /* The track control for MIDI parameters is for immediate events to act
719 as a control surface, write/touch for them is not currently
723 Automatable::set_parameter_automation_state(param, state);
728 MidiTrack::MidiControl::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
731 _set_value (val, group_override);
736 MidiTrack::MidiControl::set_value_unchecked (double val)
738 /* used only by automation playback */
739 _set_value (val, Controllable::NoGroup);
743 MidiTrack::MidiControl::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
745 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
746 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
749 if (isinf_local(val)) {
750 cerr << "MIDIControl value is infinity" << endl;
751 } else if (isnan_local(val)) {
752 cerr << "MIDIControl value is NaN" << endl;
753 } else if (val < desc.lower) {
754 cerr << "MIDIControl value is < " << desc.lower << endl;
755 } else if (val > desc.upper) {
756 cerr << "MIDIControl value is > " << desc.upper << endl;
765 assert(val <= desc.upper);
766 if ( ! _list || ! automation_playback()) {
768 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
769 switch(parameter.type()) {
770 case MidiCCAutomation:
771 ev[0] += MIDI_CMD_CONTROL;
772 ev[1] = parameter.id();
776 case MidiPgmChangeAutomation:
778 ev[0] += MIDI_CMD_PGM_CHANGE;
782 case MidiChannelPressureAutomation:
784 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
788 case MidiPitchBenderAutomation:
789 ev[0] += MIDI_CMD_BENDER;
790 ev[1] = 0x7F & int(val);
791 ev[2] = 0x7F & (int(val) >> 7);
797 _route->write_immediate_event(size, ev);
800 AutomationControl::set_value(val, group_override);
804 MidiTrack::set_step_editing (bool yn)
806 if (_session.record_status() != Session::Disabled) {
810 if (yn != _step_editing) {
812 StepEditStatusChange (yn);
816 boost::shared_ptr<SMFSource>
817 MidiTrack::write_source (uint32_t)
819 return midi_diskstream()->write_source ();
823 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
825 if (_playback_filter.set_channel_mode(mode, mask)) {
826 _session.set_dirty();
831 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
833 if (_capture_filter.set_channel_mode(mode, mask)) {
834 _session.set_dirty();
839 MidiTrack::set_playback_channel_mask (uint16_t mask)
841 if (_playback_filter.set_channel_mask(mask)) {
842 _session.set_dirty();
847 MidiTrack::set_capture_channel_mask (uint16_t mask)
849 if (_capture_filter.set_channel_mask(mask)) {
850 _session.set_dirty();
854 boost::shared_ptr<MidiPlaylist>
855 MidiTrack::midi_playlist ()
857 return midi_diskstream()->midi_playlist ();
861 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
863 DataRecorded (src); /* EMIT SIGNAL */
867 MidiTrack::input_active () const
869 return _input_active;
873 MidiTrack::set_input_active (bool yn)
875 if (yn != _input_active) {
877 map_input_active (yn);
878 InputActiveChanged (); /* EMIT SIGNAL */
883 MidiTrack::map_input_active (bool yn)
889 PortSet& ports (_input->ports());
891 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
892 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
893 if (yn != mp->input_active()) {
894 mp->set_input_active (yn);
900 MidiTrack::track_input_active (IOChange change, void* /* src */)
902 if (change.type & IOChange::ConfigurationChanged) {
903 map_input_active (_input_active);
907 boost::shared_ptr<Diskstream>
908 MidiTrack::diskstream_factory (XMLNode const & node)
910 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
913 boost::shared_ptr<MidiBuffer>
914 MidiTrack::get_gui_feed_buffer () const
916 return midi_diskstream()->get_gui_feed_buffer ();
920 MidiTrack::act_on_mute ()
922 /* this is called right after our mute status has changed.
923 if we are now muted, send suitable output to shutdown
926 XXX we should should also stop all relevant note trackers.
929 /* If we haven't got a diskstream yet, there's nothing to worry about,
930 and we can't call get_channel_mask() anyway.
932 if (!midi_diskstream()) {
936 if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) {
937 /* only send messages for channels we are using */
939 uint16_t mask = _playback_filter.get_channel_mask();
941 for (uint8_t channel = 0; channel <= 0xF; channel++) {
943 if ((1<<channel) & mask) {
945 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
946 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
947 write_immediate_event (3, ev);
949 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
950 silence notes that came from another non-muted track. */
954 /* Resolve active notes. */
955 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
960 MidiTrack::set_monitoring (MonitorChoice mc)
962 if (mc != _monitoring) {
964 Track::set_monitoring (mc);
966 /* monitoring state changed, so flush out any on notes at the
970 PortSet& ports (_output->ports());
972 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
973 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
975 mp->require_resolve ();
979 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
982 md->reset_tracker ();
988 MidiTrack::monitoring_state () const
990 MonitorState ms = Track::monitoring_state();
991 if (ms == MonitoringSilence) {
992 return MonitoringInput;