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 flush_processor_buffers_locked (nframes);
449 need_butler = diskstream->commit (playback_distance);
455 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
457 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
459 if (ret == 0 && _step_editing) {
460 push_midi_input_to_step_edit_ringbuffer (nframes);
467 MidiTrack::realtime_locate ()
469 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
475 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
476 (*i)->realtime_locate ();
479 midi_diskstream()->reset_tracker ();
483 MidiTrack::realtime_handle_transport_stopped ()
485 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
491 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
492 (*i)->realtime_handle_transport_stopped ();
497 MidiTrack::non_realtime_locate (framepos_t pos)
499 Track::non_realtime_locate(pos);
501 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
506 /* Get the top unmuted region at this position. */
507 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
508 playlist->top_unmuted_region_at(pos));
513 /* the source may be missing, but the control still referenced in the GUI */
514 if (!region->midi_source() || !region->model()) {
518 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
523 /* Update track controllers based on its "automation". */
524 const framepos_t origin = region->position() - region->start();
525 BeatsFramesConverter bfc(_session.tempo_map(), origin);
526 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
527 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
528 boost::shared_ptr<Evoral::Control> rcontrol;
529 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
530 (rcontrol = region->control(tcontrol->parameter()))) {
531 const Evoral::Beats pos_beats = bfc.from(pos - origin);
532 if (rcontrol->list()->size() > 0) {
533 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
540 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
542 PortSet& ports (_input->ports());
544 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
546 Buffer& b (p->get_buffer (nframes));
547 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
550 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
552 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
554 /* note on, since for step edit, note length is determined
558 if (ev.is_note_on()) {
559 /* we don't care about the time for this purpose */
560 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
567 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
569 MidiBuffer& buf (bufs.get_midi (0));
571 update_controls (bufs);
573 // Append immediate events
575 if (_immediate_events.read_space()) {
577 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
578 name(), _immediate_events.read_space()));
580 /* write as many of the immediate events as we can, but give "true" as
581 * the last argument ("stop on overflow in destination") so that we'll
582 * ship the rest out next time.
584 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
585 * possible position of the output buffer, so that we do not
586 * violate monotonicity when writing. Port::port_offset() will
587 * be non-zero if we're in a split process cycle.
589 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
594 MidiTrack::export_stuff (BufferSet& buffers,
597 boost::shared_ptr<Processor> endpoint,
598 bool include_endpoint,
602 if (buffers.count().n_midi() == 0) {
606 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
608 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
610 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
615 buffers.get_midi(0).clear();
616 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
620 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
625 boost::shared_ptr<Region>
626 MidiTrack::bounce (InterThreadInfo& itt)
628 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
631 boost::shared_ptr<Region>
632 MidiTrack::bounce_range (framepos_t start,
634 InterThreadInfo& itt,
635 boost::shared_ptr<Processor> endpoint,
636 bool include_endpoint)
638 vector<boost::shared_ptr<Source> > srcs;
639 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
643 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
645 std::cerr << "MIDI freeze currently unsupported" << std::endl;
649 MidiTrack::unfreeze ()
651 _freeze_record.state = UnFrozen;
652 FreezeChange (); /* EMIT SIGNAL */
656 MidiTrack::set_note_mode (NoteMode m)
659 midi_diskstream()->set_note_mode(m);
663 MidiTrack::describe_parameter (Evoral::Parameter param)
665 const std::string str(instrument_info().get_controller_name(param));
666 return str.empty() ? Automatable::describe_parameter(param) : str;
670 MidiTrack::midi_panic()
672 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
673 for (uint8_t channel = 0; channel <= 0xF; channel++) {
674 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
675 write_immediate_event(3, ev);
676 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
677 write_immediate_event(3, ev);
678 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
679 write_immediate_event(3, ev);
683 /** \return true on success, false on failure (no buffer space left)
686 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
688 if (!Evoral::midi_event_is_valid(buf, size)) {
689 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
692 const uint32_t type = midi_parameter_type(buf[0]);
693 return (_immediate_events.write (0, type, size, buf) == size);
697 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
699 switch (param.type()) {
700 case MidiCCAutomation:
701 case MidiPgmChangeAutomation:
702 case MidiPitchBenderAutomation:
703 case MidiChannelPressureAutomation:
704 case MidiNotePressureAutomation:
705 case MidiSystemExclusiveAutomation:
706 /* The track control for MIDI parameters is for immediate events to act
707 as a control surface, write/touch for them is not currently
711 Automatable::set_parameter_automation_state(param, state);
716 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
718 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
719 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
722 if (isinf_local(val)) {
723 cerr << "MIDIControl value is infinity" << endl;
724 } else if (isnan_local(val)) {
725 cerr << "MIDIControl value is NaN" << endl;
726 } else if (val < desc.lower) {
727 cerr << "MIDIControl value is < " << desc.lower << endl;
728 } else if (val > desc.upper) {
729 cerr << "MIDIControl value is > " << desc.upper << endl;
738 assert(val <= desc.upper);
739 if ( ! _list || ! automation_playback()) {
741 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
742 switch(parameter.type()) {
743 case MidiCCAutomation:
744 ev[0] += MIDI_CMD_CONTROL;
745 ev[1] = parameter.id();
749 case MidiPgmChangeAutomation:
751 ev[0] += MIDI_CMD_PGM_CHANGE;
755 case MidiChannelPressureAutomation:
757 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
761 case MidiNotePressureAutomation:
762 ev[0] += MIDI_CMD_NOTE_PRESSURE;
763 ev[1] = parameter.id();
767 case MidiPitchBenderAutomation:
768 ev[0] += MIDI_CMD_BENDER;
769 ev[1] = 0x7F & int(val);
770 ev[2] = 0x7F & (int(val) >> 7);
776 _route->write_immediate_event(size, ev);
779 AutomationControl::actually_set_value(val, group_override);
783 MidiTrack::set_step_editing (bool yn)
785 if (_session.record_status() != Session::Disabled) {
789 if (yn != _step_editing) {
791 StepEditStatusChange (yn);
795 boost::shared_ptr<SMFSource>
796 MidiTrack::write_source (uint32_t)
798 return midi_diskstream()->write_source ();
802 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
804 if (_playback_filter.set_channel_mode(mode, mask)) {
805 _session.set_dirty();
810 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
812 if (_capture_filter.set_channel_mode(mode, mask)) {
813 _session.set_dirty();
818 MidiTrack::set_playback_channel_mask (uint16_t mask)
820 if (_playback_filter.set_channel_mask(mask)) {
821 _session.set_dirty();
826 MidiTrack::set_capture_channel_mask (uint16_t mask)
828 if (_capture_filter.set_channel_mask(mask)) {
829 _session.set_dirty();
833 boost::shared_ptr<MidiPlaylist>
834 MidiTrack::midi_playlist ()
836 return midi_diskstream()->midi_playlist ();
840 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
842 DataRecorded (src); /* EMIT SIGNAL */
846 MidiTrack::input_active () const
848 return _input_active;
852 MidiTrack::set_input_active (bool yn)
854 if (yn != _input_active) {
856 map_input_active (yn);
857 InputActiveChanged (); /* EMIT SIGNAL */
862 MidiTrack::map_input_active (bool yn)
868 PortSet& ports (_input->ports());
870 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
871 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
872 if (yn != mp->input_active()) {
873 mp->set_input_active (yn);
879 MidiTrack::track_input_active (IOChange change, void* /* src */)
881 if (change.type & IOChange::ConfigurationChanged) {
882 map_input_active (_input_active);
886 boost::shared_ptr<Diskstream>
887 MidiTrack::diskstream_factory (XMLNode const & node)
889 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
892 boost::shared_ptr<MidiBuffer>
893 MidiTrack::get_gui_feed_buffer () const
895 return midi_diskstream()->get_gui_feed_buffer ();
899 MidiTrack::act_on_mute ()
901 /* this is called right after our mute status has changed.
902 if we are now muted, send suitable output to shutdown
905 XXX we should should also stop all relevant note trackers.
908 /* If we haven't got a diskstream yet, there's nothing to worry about,
909 and we can't call get_channel_mask() anyway.
911 if (!midi_diskstream()) {
915 if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
916 /* only send messages for channels we are using */
918 uint16_t mask = _playback_filter.get_channel_mask();
920 for (uint8_t channel = 0; channel <= 0xF; channel++) {
922 if ((1<<channel) & mask) {
924 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
925 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
926 write_immediate_event (3, ev);
928 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
929 silence notes that came from another non-muted track. */
933 /* Resolve active notes. */
934 midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
939 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
941 Track::monitoring_changed (self, gcd);
943 /* monitoring state changed, so flush out any on notes at the
947 PortSet& ports (_output->ports());
949 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
950 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
952 mp->require_resolve ();
956 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
959 md->reset_tracker ();
964 MidiTrack::monitoring_state () const
966 MonitorState ms = Track::monitoring_state();
967 if (ms == MonitoringSilence) {
968 return MonitoringInput;