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/monitor_control.h"
48 #include "ardour/parameter_types.h"
49 #include "ardour/port.h"
50 #include "ardour/processor.h"
51 #include "ardour/profile.h"
52 #include "ardour/route_group_specialized.h"
53 #include "ardour/session.h"
54 #include "ardour/session_playlists.h"
55 #include "ardour/utils.h"
60 class InterThreadInfo;
67 using namespace ARDOUR;
70 MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
71 : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
72 , _immediate_events(1024) // FIXME: size?
73 , _step_edit_ring_buffer(64) // FIXME: size?
74 , _note_mode(Sustained)
75 , _step_editing (false)
76 , _input_active (true)
80 MidiTrack::~MidiTrack ()
91 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
96 boost::shared_ptr<Diskstream>
97 MidiTrack::create_diskstream ()
99 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable);
101 assert(_mode != Destructive);
103 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
108 MidiTrack::can_be_record_safe ()
114 return Track::can_be_record_safe ();
118 MidiTrack::can_be_record_enabled ()
124 return Track::can_be_record_enabled ();
128 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
130 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
131 and the diskstream must be set up to fill its buffers using the correct _note_mode.
133 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
134 mds->set_note_mode (_note_mode);
136 Track::set_diskstream (ds);
138 mds->reset_tracker ();
140 _diskstream->set_track (this);
141 if (Profile->get_trx()) {
142 _diskstream->set_destructive (false);
144 _diskstream->set_destructive (_mode == Destructive);
146 _diskstream->set_record_enabled (false);
148 _diskstream_data_recorded_connection.disconnect ();
149 mds->DataRecorded.connect_same_thread (
150 _diskstream_data_recorded_connection,
151 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
153 DiskstreamChanged (); /* EMIT SIGNAL */
156 boost::shared_ptr<MidiDiskstream>
157 MidiTrack::midi_diskstream() const
159 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
163 MidiTrack::set_state (const XMLNode& node, int version)
165 XMLProperty const * prop;
167 /* This must happen before Track::set_state(), as there will be a buffer
168 fill during that call, and we must fill buffers using the correct
171 if ((prop = node.property (X_("note-mode"))) != 0) {
172 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
174 _note_mode = Sustained;
177 if (Track::set_state (node, version)) {
181 // No destructive MIDI tracks (yet?)
184 if ((prop = node.property ("input-active")) != 0) {
185 set_input_active (string_is_affirmative (prop->value()));
188 ChannelMode playback_channel_mode = AllChannels;
189 ChannelMode capture_channel_mode = AllChannels;
191 if ((prop = node.property ("playback-channel-mode")) != 0) {
192 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
194 if ((prop = node.property ("capture-channel-mode")) != 0) {
195 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
197 if ((prop = node.property ("channel-mode")) != 0) {
198 /* 3.0 behaviour where capture and playback modes were not separated */
199 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
200 capture_channel_mode = playback_channel_mode;
203 unsigned int playback_channel_mask = 0xffff;
204 unsigned int capture_channel_mask = 0xffff;
206 if ((prop = node.property ("playback-channel-mask")) != 0) {
207 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
209 if ((prop = node.property ("capture-channel-mask")) != 0) {
210 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
212 if ((prop = node.property ("channel-mask")) != 0) {
213 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
214 capture_channel_mask = playback_channel_mask;
217 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
218 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
220 pending_state = const_cast<XMLNode*> (&node);
222 if (_session.state_of_the_state() & Session::Loading) {
223 _session.StateReady.connect_same_thread (
224 *this, boost::bind (&MidiTrack::set_state_part_two, this));
226 set_state_part_two ();
233 MidiTrack::state(bool full_state)
235 XMLNode& root (Track::state(full_state));
236 XMLNode* freeze_node;
239 if (_freeze_record.playlist) {
242 freeze_node = new XMLNode (X_("freeze-info"));
243 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
244 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
246 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
247 inode = new XMLNode (X_("processor"));
248 (*i)->id.print (buf, sizeof(buf));
249 inode->add_property (X_("id"), buf);
250 inode->add_child_copy ((*i)->state);
252 freeze_node->add_child_nocopy (*inode);
255 root.add_child_nocopy (*freeze_node);
258 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
259 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
260 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
261 root.add_property("playback-channel-mask", buf);
262 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
263 root.add_property("capture-channel-mask", buf);
265 root.add_property ("note-mode", enum_2_string (_note_mode));
266 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
267 root.add_property ("input-active", (_input_active ? "yes" : "no"));
273 MidiTrack::set_state_part_two ()
276 XMLProperty const * prop;
279 /* This is called after all session state has been restored but before
280 have been made ports and connections are established.
283 if (pending_state == 0) {
287 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
289 _freeze_record.state = Frozen;
291 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
294 _freeze_record.processor_info.clear ();
296 if ((prop = fnode->property (X_("playlist"))) != 0) {
297 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
299 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
301 _freeze_record.playlist.reset();
302 _freeze_record.state = NoFreeze;
307 if ((prop = fnode->property (X_("state"))) != 0) {
308 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
311 XMLNodeConstIterator citer;
312 XMLNodeList clist = fnode->children();
314 for (citer = clist.begin(); citer != clist.end(); ++citer) {
315 if ((*citer)->name() != X_("processor")) {
319 if ((prop = (*citer)->property (X_("id"))) == 0) {
323 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
324 boost::shared_ptr<Processor>());
325 frii->id = prop->value ();
326 _freeze_record.processor_info.push_back (frii);
330 if (midi_diskstream ()) {
331 midi_diskstream()->set_block_size (_session.get_block_size ());
338 MidiTrack::update_controls(const BufferSet& bufs)
340 const MidiBuffer& buf = bufs.get_midi(0);
341 for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
342 const Evoral::MIDIEvent<framepos_t>& ev = *e;
343 const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
344 const boost::shared_ptr<Evoral::Control> control = this->control(param);
346 control->set_double(ev.value(), _session.transport_frame(), false);
351 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
355 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
357 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
359 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
360 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
361 if (can_internal_playback_seek(::llabs(playback_distance))) {
362 /* TODO should declick, and/or note-off */
363 internal_playback_seek(playback_distance);
368 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
370 if (n_outputs().n_total() == 0 && _processors.empty()) {
376 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
382 framepos_t transport_frame = _session.transport_frame();
385 framecnt_t playback_distance;
387 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
388 /* need to do this so that the diskstream sets its
389 playback distance to zero, thus causing diskstream::commit
392 BufferSet bufs; /* empty set - is OK, since nothing will happen */
394 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
395 need_butler = diskstream->commit (playback_distance);
399 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
401 fill_buffers_with_input (bufs, _input, nframes);
403 /* filter captured data before meter sees it */
404 _capture_filter.filter (bufs);
406 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) {
407 _meter->run (bufs, start_frame, end_frame, 1.0 /*speed()*/, nframes, true);
413 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
414 need_butler = diskstream->commit (playback_distance);
419 /* note diskstream uses our filter to filter/map playback channels appropriately. */
421 if (monitoring_state() == MonitoringInput) {
423 /* not actually recording, but we want to hear the input material anyway,
424 at least potentially (depending on monitoring options)
427 /* because the playback buffer is event based and not a
428 * continuous stream, we need to make sure that we empty
429 * it of events every cycle to avoid it filling up with events
430 * read from disk, while we are actually monitoring input
433 diskstream->flush_playback (start_frame, end_frame);
438 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
440 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
442 /* final argument: don't waste time with automation if we're not recording or rolling */
444 process_output_buffers (bufs, start_frame, end_frame, nframes,
445 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
447 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
448 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
450 d->flush_buffers (nframes);
454 need_butler = diskstream->commit (playback_distance);
460 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
462 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
464 if (ret == 0 && _step_editing) {
465 push_midi_input_to_step_edit_ringbuffer (nframes);
472 MidiTrack::realtime_locate ()
474 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
480 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
481 (*i)->realtime_locate ();
484 midi_diskstream()->reset_tracker ();
488 MidiTrack::realtime_handle_transport_stopped ()
490 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
496 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
497 (*i)->realtime_handle_transport_stopped ();
502 MidiTrack::non_realtime_locate (framepos_t pos)
504 Track::non_realtime_locate(pos);
506 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
511 /* Get the top unmuted region at this position. */
512 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
513 playlist->top_unmuted_region_at(pos));
518 /* the source may be missing, but the control still referenced in the GUI */
519 if (!region->midi_source() || !region->model()) {
523 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
528 /* Update track controllers based on its "automation". */
529 const framepos_t origin = region->position() - region->start();
530 BeatsFramesConverter bfc(_session.tempo_map(), origin);
531 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
532 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
533 boost::shared_ptr<Evoral::Control> rcontrol;
534 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
535 (rcontrol = region->control(tcontrol->parameter()))) {
536 const Evoral::Beats pos_beats = bfc.from(pos - origin);
537 if (rcontrol->list()->size() > 0) {
538 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
545 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
547 PortSet& ports (_input->ports());
549 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
551 Buffer& b (p->get_buffer (nframes));
552 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
555 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
557 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
559 /* note on, since for step edit, note length is determined
563 if (ev.is_note_on()) {
564 /* we don't care about the time for this purpose */
565 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
572 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
574 MidiBuffer& buf (bufs.get_midi (0));
576 update_controls (bufs);
578 // Append immediate events
580 if (_immediate_events.read_space()) {
582 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
583 name(), _immediate_events.read_space()));
585 /* write as many of the immediate events as we can, but give "true" as
586 * the last argument ("stop on overflow in destination") so that we'll
587 * ship the rest out next time.
589 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
590 * possible position of the output buffer, so that we do not
591 * violate monotonicity when writing. Port::port_offset() will
592 * be non-zero if we're in a split process cycle.
594 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
599 MidiTrack::export_stuff (BufferSet& buffers,
602 boost::shared_ptr<Processor> endpoint,
603 bool include_endpoint,
607 if (buffers.count().n_midi() == 0) {
611 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
613 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
615 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
620 buffers.get_midi(0).clear();
621 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
625 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
630 boost::shared_ptr<Region>
631 MidiTrack::bounce (InterThreadInfo& itt)
633 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
636 boost::shared_ptr<Region>
637 MidiTrack::bounce_range (framepos_t start,
639 InterThreadInfo& itt,
640 boost::shared_ptr<Processor> endpoint,
641 bool include_endpoint)
643 vector<boost::shared_ptr<Source> > srcs;
644 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
648 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
650 std::cerr << "MIDI freeze currently unsupported" << std::endl;
654 MidiTrack::unfreeze ()
656 _freeze_record.state = UnFrozen;
657 FreezeChange (); /* EMIT SIGNAL */
661 MidiTrack::set_note_mode (NoteMode m)
664 midi_diskstream()->set_note_mode(m);
668 MidiTrack::describe_parameter (Evoral::Parameter param)
670 const std::string str(instrument_info().get_controller_name(param));
671 return str.empty() ? Automatable::describe_parameter(param) : str;
675 MidiTrack::midi_panic()
677 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
678 for (uint8_t channel = 0; channel <= 0xF; channel++) {
679 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
680 write_immediate_event(3, ev);
681 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
682 write_immediate_event(3, ev);
683 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
684 write_immediate_event(3, ev);
688 /** \return true on success, false on failure (no buffer space left)
691 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
693 if (!Evoral::midi_event_is_valid(buf, size)) {
694 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
697 const uint32_t type = midi_parameter_type(buf[0]);
698 return (_immediate_events.write (0, type, size, buf) == size);
702 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
704 switch (param.type()) {
705 case MidiCCAutomation:
706 case MidiPgmChangeAutomation:
707 case MidiPitchBenderAutomation:
708 case MidiChannelPressureAutomation:
709 case MidiSystemExclusiveAutomation:
710 /* The track control for MIDI parameters is for immediate events to act
711 as a control surface, write/touch for them is not currently
715 Automatable::set_parameter_automation_state(param, state);
720 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
722 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
723 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
726 if (isinf_local(val)) {
727 cerr << "MIDIControl value is infinity" << endl;
728 } else if (isnan_local(val)) {
729 cerr << "MIDIControl value is NaN" << endl;
730 } else if (val < desc.lower) {
731 cerr << "MIDIControl value is < " << desc.lower << endl;
732 } else if (val > desc.upper) {
733 cerr << "MIDIControl value is > " << desc.upper << endl;
742 assert(val <= desc.upper);
743 if ( ! _list || ! automation_playback()) {
745 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
746 switch(parameter.type()) {
747 case MidiCCAutomation:
748 ev[0] += MIDI_CMD_CONTROL;
749 ev[1] = parameter.id();
753 case MidiPgmChangeAutomation:
755 ev[0] += MIDI_CMD_PGM_CHANGE;
759 case MidiChannelPressureAutomation:
761 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
765 case MidiPitchBenderAutomation:
766 ev[0] += MIDI_CMD_BENDER;
767 ev[1] = 0x7F & int(val);
768 ev[2] = 0x7F & (int(val) >> 7);
774 _route->write_immediate_event(size, ev);
777 AutomationControl::actually_set_value(val, group_override);
781 MidiTrack::set_step_editing (bool yn)
783 if (_session.record_status() != Session::Disabled) {
787 if (yn != _step_editing) {
789 StepEditStatusChange (yn);
793 boost::shared_ptr<SMFSource>
794 MidiTrack::write_source (uint32_t)
796 return midi_diskstream()->write_source ();
800 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
802 if (_playback_filter.set_channel_mode(mode, mask)) {
803 _session.set_dirty();
808 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
810 if (_capture_filter.set_channel_mode(mode, mask)) {
811 _session.set_dirty();
816 MidiTrack::set_playback_channel_mask (uint16_t mask)
818 if (_playback_filter.set_channel_mask(mask)) {
819 _session.set_dirty();
824 MidiTrack::set_capture_channel_mask (uint16_t mask)
826 if (_capture_filter.set_channel_mask(mask)) {
827 _session.set_dirty();
831 boost::shared_ptr<MidiPlaylist>
832 MidiTrack::midi_playlist ()
834 return midi_diskstream()->midi_playlist ();
838 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
840 DataRecorded (src); /* EMIT SIGNAL */
844 MidiTrack::input_active () const
846 return _input_active;
850 MidiTrack::set_input_active (bool yn)
852 if (yn != _input_active) {
854 map_input_active (yn);
855 InputActiveChanged (); /* EMIT SIGNAL */
860 MidiTrack::map_input_active (bool yn)
866 PortSet& ports (_input->ports());
868 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
869 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
870 if (yn != mp->input_active()) {
871 mp->set_input_active (yn);
877 MidiTrack::track_input_active (IOChange change, void* /* src */)
879 if (change.type & IOChange::ConfigurationChanged) {
880 map_input_active (_input_active);
884 boost::shared_ptr<Diskstream>
885 MidiTrack::diskstream_factory (XMLNode const & node)
887 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
890 boost::shared_ptr<MidiBuffer>
891 MidiTrack::get_gui_feed_buffer () const
893 return midi_diskstream()->get_gui_feed_buffer ();
897 MidiTrack::act_on_mute ()
899 /* this is called right after our mute status has changed.
900 if we are now muted, send suitable output to shutdown
903 XXX we should should also stop all relevant note trackers.
906 /* If we haven't got a diskstream yet, there's nothing to worry about,
907 and we can't call get_channel_mask() anyway.
909 if (!midi_diskstream()) {
913 if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
914 /* only send messages for channels we are using */
916 uint16_t mask = _playback_filter.get_channel_mask();
918 for (uint8_t channel = 0; channel <= 0xF; channel++) {
920 if ((1<<channel) & mask) {
922 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
923 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
924 write_immediate_event (3, ev);
926 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
927 silence notes that came from another non-muted track. */
931 /* Resolve active notes. */
932 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
937 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
939 Track::monitoring_changed (self, gcd);
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 ();
962 MidiTrack::monitoring_state () const
964 MonitorState ms = Track::monitoring_state();
965 if (ms == MonitoringSilence) {
966 return MonitoringInput;