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/route_group_specialized.h"
52 #include "ardour/session.h"
53 #include "ardour/session_playlists.h"
54 #include "ardour/utils.h"
59 class InterThreadInfo;
66 using namespace ARDOUR;
69 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
70 : Track (sess, name, flag, mode, DataType::MIDI)
71 , _immediate_events(1024) // FIXME: size?
72 , _step_edit_ring_buffer(64) // FIXME: size?
73 , _note_mode(Sustained)
74 , _step_editing (false)
75 , _input_active (true)
79 MidiTrack::~MidiTrack ()
90 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
95 boost::shared_ptr<Diskstream>
96 MidiTrack::create_diskstream ()
98 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable);
100 assert(_mode != Destructive);
102 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
107 MidiTrack::set_record_enabled (bool yn, Controllable::GroupControlDisposition group_override)
113 Track::set_record_enabled (yn, group_override);
117 MidiTrack::set_record_safe (bool yn, Controllable::GroupControlDisposition group_override)
119 if (_step_editing) { /* REQUIRES REVIEW */
123 Track::set_record_safe (yn, group_override);
127 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
129 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
130 and the diskstream must be set up to fill its buffers using the correct _note_mode.
132 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
133 mds->set_note_mode (_note_mode);
135 Track::set_diskstream (ds);
137 mds->reset_tracker ();
139 _diskstream->set_track (this);
140 if (Profile->get_trx()) {
141 _diskstream->set_destructive (false);
143 _diskstream->set_destructive (_mode == Destructive);
145 _diskstream->set_record_enabled (false);
147 _diskstream_data_recorded_connection.disconnect ();
148 mds->DataRecorded.connect_same_thread (
149 _diskstream_data_recorded_connection,
150 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
152 DiskstreamChanged (); /* EMIT SIGNAL */
155 boost::shared_ptr<MidiDiskstream>
156 MidiTrack::midi_diskstream() const
158 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
162 MidiTrack::set_state (const XMLNode& node, int version)
164 XMLProperty const * prop;
166 /* This must happen before Track::set_state(), as there will be a buffer
167 fill during that call, and we must fill buffers using the correct
170 if ((prop = node.property (X_("note-mode"))) != 0) {
171 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
173 _note_mode = Sustained;
176 if (Track::set_state (node, version)) {
180 // No destructive MIDI tracks (yet?)
183 if ((prop = node.property ("input-active")) != 0) {
184 set_input_active (string_is_affirmative (prop->value()));
187 ChannelMode playback_channel_mode = AllChannels;
188 ChannelMode capture_channel_mode = AllChannels;
190 if ((prop = node.property ("playback-channel-mode")) != 0) {
191 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
193 if ((prop = node.property ("capture-channel-mode")) != 0) {
194 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
196 if ((prop = node.property ("channel-mode")) != 0) {
197 /* 3.0 behaviour where capture and playback modes were not separated */
198 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
199 capture_channel_mode = playback_channel_mode;
202 unsigned int playback_channel_mask = 0xffff;
203 unsigned int capture_channel_mask = 0xffff;
205 if ((prop = node.property ("playback-channel-mask")) != 0) {
206 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
208 if ((prop = node.property ("capture-channel-mask")) != 0) {
209 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
211 if ((prop = node.property ("channel-mask")) != 0) {
212 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
213 capture_channel_mask = playback_channel_mask;
216 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
217 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
219 pending_state = const_cast<XMLNode*> (&node);
221 if (_session.state_of_the_state() & Session::Loading) {
222 _session.StateReady.connect_same_thread (
223 *this, boost::bind (&MidiTrack::set_state_part_two, this));
225 set_state_part_two ();
232 MidiTrack::state(bool full_state)
234 XMLNode& root (Track::state(full_state));
235 XMLNode* freeze_node;
238 if (_freeze_record.playlist) {
241 freeze_node = new XMLNode (X_("freeze-info"));
242 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
243 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
245 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
246 inode = new XMLNode (X_("processor"));
247 (*i)->id.print (buf, sizeof(buf));
248 inode->add_property (X_("id"), buf);
249 inode->add_child_copy ((*i)->state);
251 freeze_node->add_child_nocopy (*inode);
254 root.add_child_nocopy (*freeze_node);
257 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
258 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
259 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
260 root.add_property("playback-channel-mask", buf);
261 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
262 root.add_property("capture-channel-mask", buf);
264 root.add_property ("note-mode", enum_2_string (_note_mode));
265 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
266 root.add_property ("input-active", (_input_active ? "yes" : "no"));
272 MidiTrack::set_state_part_two ()
275 XMLProperty const * prop;
278 /* This is called after all session state has been restored but before
279 have been made ports and connections are established.
282 if (pending_state == 0) {
286 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
288 _freeze_record.state = Frozen;
290 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
293 _freeze_record.processor_info.clear ();
295 if ((prop = fnode->property (X_("playlist"))) != 0) {
296 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
298 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
300 _freeze_record.playlist.reset();
301 _freeze_record.state = NoFreeze;
306 if ((prop = fnode->property (X_("state"))) != 0) {
307 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
310 XMLNodeConstIterator citer;
311 XMLNodeList clist = fnode->children();
313 for (citer = clist.begin(); citer != clist.end(); ++citer) {
314 if ((*citer)->name() != X_("processor")) {
318 if ((prop = (*citer)->property (X_("id"))) == 0) {
322 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
323 boost::shared_ptr<Processor>());
324 frii->id = prop->value ();
325 _freeze_record.processor_info.push_back (frii);
329 if (midi_diskstream ()) {
330 midi_diskstream()->set_block_size (_session.get_block_size ());
337 MidiTrack::update_controls(const BufferSet& bufs)
339 const MidiBuffer& buf = bufs.get_midi(0);
340 for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
341 const Evoral::MIDIEvent<framepos_t>& ev = *e;
342 const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
343 const boost::shared_ptr<Evoral::Control> control = this->control(param);
345 control->set_double(ev.value(), _session.transport_frame(), false);
350 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
354 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
356 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
358 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
359 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
360 if (can_internal_playback_seek(::llabs(playback_distance))) {
361 /* TODO should declick, and/or note-off */
362 internal_playback_seek(playback_distance);
367 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
369 if (n_outputs().n_total() == 0 && _processors.empty()) {
375 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
381 framepos_t transport_frame = _session.transport_frame();
384 framecnt_t playback_distance;
386 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
387 /* need to do this so that the diskstream sets its
388 playback distance to zero, thus causing diskstream::commit
391 BufferSet bufs; /* empty set - is OK, since nothing will happen */
393 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
394 need_butler = diskstream->commit (playback_distance);
398 if (_mute_control->list() && _mute_control->automation_playback()) {
400 const float mute = _mute_control->list()->rt_safe_eval(transport_frame, valid);
401 if (mute >= 0.5 && !muted()) {
402 _mute_control->set_value_unchecked(1.0); // mute
403 } else if (mute < 0.5 && muted()) {
404 _mute_control->set_value_unchecked(0.0); // unmute
408 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
410 fill_buffers_with_input (bufs, _input, nframes);
412 /* filter captured data before meter sees it */
413 _capture_filter.filter (bufs);
415 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
416 _meter->run (bufs, start_frame, end_frame, nframes, true);
422 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
423 need_butler = diskstream->commit (playback_distance);
428 /* note diskstream uses our filter to filter/map playback channels appropriately. */
430 if (monitoring_state() == MonitoringInput) {
432 /* not actually recording, but we want to hear the input material anyway,
433 at least potentially (depending on monitoring options)
436 /* because the playback buffer is event based and not a
437 * continuous stream, we need to make sure that we empty
438 * it of events every cycle to avoid it filling up with events
439 * read from disk, while we are actually monitoring input
442 diskstream->flush_playback (start_frame, end_frame);
447 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
449 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
451 /* final argument: don't waste time with automation if we're not recording or rolling */
453 process_output_buffers (bufs, start_frame, end_frame, nframes,
454 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
456 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
457 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
459 d->flush_buffers (nframes);
463 need_butler = diskstream->commit (playback_distance);
469 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
471 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
473 if (ret == 0 && _step_editing) {
474 push_midi_input_to_step_edit_ringbuffer (nframes);
481 MidiTrack::realtime_locate ()
483 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
489 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
490 (*i)->realtime_locate ();
493 midi_diskstream()->reset_tracker ();
497 MidiTrack::realtime_handle_transport_stopped ()
499 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
505 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
506 (*i)->realtime_handle_transport_stopped ();
511 MidiTrack::non_realtime_locate (framepos_t pos)
513 Track::non_realtime_locate(pos);
515 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
520 /* Get the top unmuted region at this position. */
521 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
522 playlist->top_unmuted_region_at(pos));
527 /* the source may be missing, but the control still referenced in the GUI */
528 if (!region->midi_source() || !region->model()) {
532 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
537 /* Update track controllers based on its "automation". */
538 const framepos_t origin = region->position() - region->start();
539 BeatsFramesConverter bfc(_session.tempo_map(), origin);
540 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
541 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
542 boost::shared_ptr<Evoral::Control> rcontrol;
543 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
544 (rcontrol = region->control(tcontrol->parameter()))) {
545 const Evoral::Beats pos_beats = bfc.from(pos - origin);
546 if (rcontrol->list()->size() > 0) {
547 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
554 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
556 PortSet& ports (_input->ports());
558 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
560 Buffer& b (p->get_buffer (nframes));
561 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
564 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
566 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
568 /* note on, since for step edit, note length is determined
572 if (ev.is_note_on()) {
573 /* we don't care about the time for this purpose */
574 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
581 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
583 MidiBuffer& buf (bufs.get_midi (0));
585 update_controls (bufs);
587 // Append immediate events
589 if (_immediate_events.read_space()) {
591 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
592 name(), _immediate_events.read_space()));
594 /* write as many of the immediate events as we can, but give "true" as
595 * the last argument ("stop on overflow in destination") so that we'll
596 * ship the rest out next time.
598 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
599 * possible position of the output buffer, so that we do not
600 * violate monotonicity when writing. Port::port_offset() will
601 * be non-zero if we're in a split process cycle.
603 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
608 MidiTrack::export_stuff (BufferSet& buffers,
611 boost::shared_ptr<Processor> endpoint,
612 bool include_endpoint,
616 if (buffers.count().n_midi() == 0) {
620 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
622 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
624 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
629 buffers.get_midi(0).clear();
630 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
634 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
639 boost::shared_ptr<Region>
640 MidiTrack::bounce (InterThreadInfo& itt)
642 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
645 boost::shared_ptr<Region>
646 MidiTrack::bounce_range (framepos_t start,
648 InterThreadInfo& itt,
649 boost::shared_ptr<Processor> endpoint,
650 bool include_endpoint)
652 vector<boost::shared_ptr<Source> > srcs;
653 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
657 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
659 std::cerr << "MIDI freeze currently unsupported" << std::endl;
663 MidiTrack::unfreeze ()
665 _freeze_record.state = UnFrozen;
666 FreezeChange (); /* EMIT SIGNAL */
670 MidiTrack::set_note_mode (NoteMode m)
673 midi_diskstream()->set_note_mode(m);
677 MidiTrack::describe_parameter (Evoral::Parameter param)
679 const std::string str(instrument_info().get_controller_name(param));
680 return str.empty() ? Automatable::describe_parameter(param) : str;
684 MidiTrack::midi_panic()
686 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
687 for (uint8_t channel = 0; channel <= 0xF; channel++) {
688 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
689 write_immediate_event(3, ev);
690 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
691 write_immediate_event(3, ev);
692 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
693 write_immediate_event(3, ev);
697 /** \return true on success, false on failure (no buffer space left)
700 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
702 if (!Evoral::midi_event_is_valid(buf, size)) {
703 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
706 const uint32_t type = midi_parameter_type(buf[0]);
707 return (_immediate_events.write (0, type, size, buf) == size);
711 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
713 switch (param.type()) {
714 case MidiCCAutomation:
715 case MidiPgmChangeAutomation:
716 case MidiPitchBenderAutomation:
717 case MidiChannelPressureAutomation:
718 case MidiSystemExclusiveAutomation:
719 /* The track control for MIDI parameters is for immediate events to act
720 as a control surface, write/touch for them is not currently
724 Automatable::set_parameter_automation_state(param, state);
729 MidiTrack::MidiControl::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
732 _set_value (val, group_override);
737 MidiTrack::MidiControl::set_value_unchecked (double val)
739 /* used only by automation playback */
740 _set_value (val, Controllable::NoGroup);
744 MidiTrack::MidiControl::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
746 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
747 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
750 if (isinf_local(val)) {
751 cerr << "MIDIControl value is infinity" << endl;
752 } else if (isnan_local(val)) {
753 cerr << "MIDIControl value is NaN" << endl;
754 } else if (val < desc.lower) {
755 cerr << "MIDIControl value is < " << desc.lower << endl;
756 } else if (val > desc.upper) {
757 cerr << "MIDIControl value is > " << desc.upper << endl;
766 assert(val <= desc.upper);
767 if ( ! _list || ! automation_playback()) {
769 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
770 switch(parameter.type()) {
771 case MidiCCAutomation:
772 ev[0] += MIDI_CMD_CONTROL;
773 ev[1] = parameter.id();
777 case MidiPgmChangeAutomation:
779 ev[0] += MIDI_CMD_PGM_CHANGE;
783 case MidiChannelPressureAutomation:
785 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
789 case MidiPitchBenderAutomation:
790 ev[0] += MIDI_CMD_BENDER;
791 ev[1] = 0x7F & int(val);
792 ev[2] = 0x7F & (int(val) >> 7);
798 _route->write_immediate_event(size, ev);
801 AutomationControl::set_value(val, group_override);
805 MidiTrack::set_step_editing (bool yn)
807 if (_session.record_status() != Session::Disabled) {
811 if (yn != _step_editing) {
813 StepEditStatusChange (yn);
817 boost::shared_ptr<SMFSource>
818 MidiTrack::write_source (uint32_t)
820 return midi_diskstream()->write_source ();
824 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
826 if (_playback_filter.set_channel_mode(mode, mask)) {
827 _session.set_dirty();
832 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
834 if (_capture_filter.set_channel_mode(mode, mask)) {
835 _session.set_dirty();
840 MidiTrack::set_playback_channel_mask (uint16_t mask)
842 if (_playback_filter.set_channel_mask(mask)) {
843 _session.set_dirty();
848 MidiTrack::set_capture_channel_mask (uint16_t mask)
850 if (_capture_filter.set_channel_mask(mask)) {
851 _session.set_dirty();
855 boost::shared_ptr<MidiPlaylist>
856 MidiTrack::midi_playlist ()
858 return midi_diskstream()->midi_playlist ();
862 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
864 DataRecorded (src); /* EMIT SIGNAL */
868 MidiTrack::input_active () const
870 return _input_active;
874 MidiTrack::set_input_active (bool yn)
876 if (yn != _input_active) {
878 map_input_active (yn);
879 InputActiveChanged (); /* EMIT SIGNAL */
884 MidiTrack::map_input_active (bool yn)
890 PortSet& ports (_input->ports());
892 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
893 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
894 if (yn != mp->input_active()) {
895 mp->set_input_active (yn);
901 MidiTrack::track_input_active (IOChange change, void* /* src */)
903 if (change.type & IOChange::ConfigurationChanged) {
904 map_input_active (_input_active);
908 boost::shared_ptr<Diskstream>
909 MidiTrack::diskstream_factory (XMLNode const & node)
911 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
914 boost::shared_ptr<MidiBuffer>
915 MidiTrack::get_gui_feed_buffer () const
917 return midi_diskstream()->get_gui_feed_buffer ();
921 MidiTrack::act_on_mute ()
923 /* this is called right after our mute status has changed.
924 if we are now muted, send suitable output to shutdown
927 XXX we should should also stop all relevant note trackers.
930 /* If we haven't got a diskstream yet, there's nothing to worry about,
931 and we can't call get_channel_mask() anyway.
933 if (!midi_diskstream()) {
937 if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) {
938 /* only send messages for channels we are using */
940 uint16_t mask = _playback_filter.get_channel_mask();
942 for (uint8_t channel = 0; channel <= 0xF; channel++) {
944 if ((1<<channel) & mask) {
946 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
947 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
948 write_immediate_event (3, ev);
950 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
951 silence notes that came from another non-muted track. */
955 /* Resolve active notes. */
956 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
961 MidiTrack::set_monitoring (MonitorChoice mc, Controllable::GroupControlDisposition gcd)
963 if (use_group (gcd, &RouteGroup::is_monitoring)) {
964 _route_group->apply (&Track::set_monitoring, mc, Controllable::NoGroup);
968 if (mc != _monitoring) {
970 Track::set_monitoring (mc, gcd);
972 /* monitoring state changed, so flush out any on notes at the
976 PortSet& ports (_output->ports());
978 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
979 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
981 mp->require_resolve ();
985 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
988 md->reset_tracker ();
994 MidiTrack::monitoring_state () const
996 MonitorState ms = Track::monitoring_state();
997 if (ms == MonitoringSilence) {
998 return MonitoringInput;