be85bc1d4984604801a6fef317d784866d51f148
[ardour.git] / libs / ardour / midi_track.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3     Author: David Robillard
4
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.
9
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.
14
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.
18 */
19 #include <cmath>
20
21 #ifdef COMPILER_MSVC
22 #include <float.h>
23
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)
27 #else
28 #define isinf_local std::isinf
29 #define isnan_local std::isnan
30 #endif
31
32 #include "pbd/enumwriter.h"
33 #include "pbd/types_convert.h"
34 #include "evoral/midi_util.h"
35
36 #include "ardour/amp.h"
37 #include "ardour/beats_frames_converter.h"
38 #include "ardour/buffer_set.h"
39 #include "ardour/debug.h"
40 #include "ardour/delivery.h"
41 #include "ardour/disk_reader.h"
42 #include "ardour/disk_writer.h"
43 #include "ardour/event_type_map.h"
44 #include "ardour/meter.h"
45 #include "ardour/midi_playlist.h"
46 #include "ardour/midi_port.h"
47 #include "ardour/midi_region.h"
48 #include "ardour/midi_track.h"
49 #include "ardour/monitor_control.h"
50 #include "ardour/parameter_types.h"
51 #include "ardour/port.h"
52 #include "ardour/processor.h"
53 #include "ardour/profile.h"
54 #include "ardour/route_group_specialized.h"
55 #include "ardour/session.h"
56 #include "ardour/session_playlists.h"
57 #include "ardour/types_convert.h"
58 #include "ardour/utils.h"
59
60 #include "pbd/i18n.h"
61
62 namespace ARDOUR {
63 class InterThreadInfo;
64 class MidiSource;
65 class Region;
66 class SMFSource;
67 }
68
69 using namespace std;
70 using namespace ARDOUR;
71 using namespace PBD;
72
73 MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
74         : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
75         , _immediate_events(6096) // FIXME: size?
76         , _step_edit_ring_buffer(64) // FIXME: size?
77         , _note_mode (Sustained)
78         , _step_editing (false)
79         , _input_active (true)
80 {
81         _session.SessionLoaded.connect_same_thread (*this, boost::bind (&MidiTrack::restore_controls, this));
82
83         _disk_writer->set_note_mode (_note_mode);
84         _disk_reader->reset_tracker ();
85
86 }
87
88 MidiTrack::~MidiTrack ()
89 {
90 }
91
92 int
93 MidiTrack::init ()
94 {
95         if (Track::init ()) {
96                 return -1;
97         }
98
99         _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
100
101         return 0;
102 }
103
104 bool
105 MidiTrack::can_be_record_safe ()
106 {
107         if (_step_editing) {
108                 return false;
109         }
110
111         return Track::can_be_record_safe ();
112 }
113
114 bool
115 MidiTrack::can_be_record_enabled ()
116 {
117         if (_step_editing) {
118                 return false;
119         }
120
121         return Track::can_be_record_enabled ();
122 }
123
124 int
125 MidiTrack::set_state (const XMLNode& node, int version)
126 {
127         /* This must happen before Track::set_state(), as there will be a buffer
128            fill during that call, and we must fill buffers using the correct
129            _note_mode.
130         */
131         if (!node.get_property (X_("note-mode"), _note_mode)) {
132                 _note_mode = Sustained;
133         }
134
135         if (Track::set_state (node, version)) {
136                 return -1;
137         }
138
139         // No destructive MIDI tracks (yet?)
140         _mode = Normal;
141
142         bool yn;
143         if (node.get_property ("input-active", yn)) {
144                 set_input_active (yn);
145         }
146
147         ChannelMode playback_channel_mode = AllChannels;
148         ChannelMode capture_channel_mode = AllChannels;
149
150         node.get_property ("playback-channel-mode", playback_channel_mode);
151         node.get_property ("capture-channel-mode", capture_channel_mode);
152
153         if (node.get_property ("channel-mode", playback_channel_mode)) {
154                 /* 3.0 behaviour where capture and playback modes were not separated */
155                 capture_channel_mode = playback_channel_mode;
156         }
157
158         XMLProperty const * prop;
159
160         unsigned int playback_channel_mask = 0xffff;
161         unsigned int capture_channel_mask = 0xffff;
162
163         if ((prop = node.property ("playback-channel-mask")) != 0) {
164                 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
165         }
166         if ((prop = node.property ("capture-channel-mask")) != 0) {
167                 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
168         }
169         if ((prop = node.property ("channel-mask")) != 0) {
170                 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
171                 capture_channel_mask = playback_channel_mask;
172         }
173
174         set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
175         set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
176
177         pending_state = const_cast<XMLNode*> (&node);
178
179         if (_session.state_of_the_state() & Session::Loading) {
180                 _session.StateReady.connect_same_thread (
181                         *this, boost::bind (&MidiTrack::set_state_part_two, this));
182         } else {
183                 set_state_part_two ();
184         }
185
186         return 0;
187 }
188
189 XMLNode&
190 MidiTrack::state(bool full_state)
191 {
192         XMLNode& root (Track::state(full_state));
193         XMLNode* freeze_node;
194         char buf[64];
195
196         if (_freeze_record.playlist) {
197                 XMLNode* inode;
198
199                 freeze_node = new XMLNode (X_("freeze-info"));
200                 freeze_node->set_property ("playlist", _freeze_record.playlist->name());
201                 freeze_node->set_property ("state", _freeze_record.state);
202
203                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
204                         inode = new XMLNode (X_("processor"));
205                         inode->set_property (X_("id"), id());
206                         inode->add_child_copy ((*i)->state);
207
208                         freeze_node->add_child_nocopy (*inode);
209                 }
210
211                 root.add_child_nocopy (*freeze_node);
212         }
213
214         root.set_property("playback-channel-mode", get_playback_channel_mode());
215         root.set_property("capture-channel-mode", get_capture_channel_mode());
216         snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
217         root.set_property("playback-channel-mask", std::string(buf));
218         snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
219         root.set_property("capture-channel-mask", std::string(buf));
220
221         root.set_property ("note-mode", _note_mode);
222         root.set_property ("step-editing", _step_editing);
223         root.set_property ("input-active", _input_active);
224
225         for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
226                 if (boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) {
227                         boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c->second);
228                         assert (ac);
229                         root.add_child_nocopy (ac->get_state ());
230                 }
231         }
232
233         return root;
234 }
235
236 void
237 MidiTrack::set_state_part_two ()
238 {
239         XMLNode* fnode;
240
241         /* This is called after all session state has been restored but before
242            have been made ports and connections are established.
243         */
244
245         if (pending_state == 0) {
246                 return;
247         }
248
249         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
250
251                 _freeze_record.state = Frozen;
252
253                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
254                         delete *i;
255                 }
256                 _freeze_record.processor_info.clear ();
257
258                 std::string str;
259                 if (fnode->get_property (X_("playlist"), str)) {
260                         boost::shared_ptr<Playlist> pl = _session.playlists->by_name (str);
261                         if (pl) {
262                                 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
263                         } else {
264                                 _freeze_record.playlist.reset();
265                                 _freeze_record.state = NoFreeze;
266                                 return;
267                         }
268                 }
269
270                 fnode->get_property (X_("state"), _freeze_record.state);
271
272                 XMLNodeConstIterator citer;
273                 XMLNodeList clist = fnode->children();
274
275                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
276                         if ((*citer)->name() != X_("processor")) {
277                                 continue;
278                         }
279
280                         if (!(*citer)->get_property (X_("id"), str)) {
281                                 continue;
282                         }
283
284                         FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
285                                                                                    boost::shared_ptr<Processor>());
286                         frii->id = str;
287                         _freeze_record.processor_info.push_back (frii);
288                 }
289         }
290
291         return;
292 }
293
294 void
295 MidiTrack::restore_controls ()
296 {
297         // TODO order events (CC before PGM to set banks)
298         for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
299                 boost::shared_ptr<MidiTrack::MidiControl> mctrl = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second);
300                 if (mctrl) {
301                         mctrl->restore_value();
302                 }
303         }
304 }
305
306 void
307 MidiTrack::update_controls(const BufferSet& bufs)
308 {
309         const MidiBuffer& buf = bufs.get_midi(0);
310         for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
311                 const Evoral::Event<framepos_t>&         ev      = *e;
312                 const Evoral::Parameter                  param   = midi_parameter(ev.buffer(), ev.size());
313                 const boost::shared_ptr<AutomationControl> control = automation_control (param);
314                 if (control) {
315                         control->set_double(ev.value(), _session.transport_frame(), false);
316                         control->Changed (false, Controllable::NoGroup);
317                 }
318         }
319 }
320
321 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
322  *  or set to false.
323  */
324 int
325 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
326 {
327         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
328
329         if (!lm.locked()) {
330                 return 0;
331         }
332
333         if (n_outputs().n_total() == 0 && _processors.empty()) {
334                 return 0;
335         }
336
337         if (!_active) {
338                 silence (nframes);
339                 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) {
340                         _meter->reset();
341                 }
342                 return 0;
343         }
344
345         _silent = false;
346         _amp->apply_gain_automation (false);
347
348         BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
349
350         fill_buffers_with_input (bufs, _input, nframes);
351
352         /* filter captured data before meter sees it */
353         _capture_filter.filter (bufs);
354
355         if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) {
356                 _meter->run (bufs, start_frame, end_frame, 1.0 /*speed()*/, nframes, true);
357         }
358
359         /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
360
361         write_out_of_band_data (bufs, start_frame, end_frame, nframes);
362
363         /* final argument: don't waste time with automation if we're not recording or rolling */
364
365         process_output_buffers (bufs, start_frame, end_frame, nframes, declick, (!_disk_writer->record_enabled() && !_session.transport_stopped()));
366
367         flush_processor_buffers_locked (nframes);
368
369         return 0;
370 }
371
372 int
373 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
374 {
375         int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
376
377         if (ret == 0 && _step_editing) {
378                 push_midi_input_to_step_edit_ringbuffer (nframes);
379         }
380
381         return ret;
382 }
383
384 void
385 MidiTrack::realtime_locate ()
386 {
387         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
388
389         if (!lm.locked ()) {
390                 return;
391         }
392
393         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
394                 (*i)->realtime_locate ();
395         }
396
397         _disk_reader->reset_tracker ();
398 }
399
400 void
401 MidiTrack::realtime_handle_transport_stopped ()
402 {
403         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
404
405         if (!lm.locked ()) {
406                 return;
407         }
408
409         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
410                 (*i)->realtime_handle_transport_stopped ();
411         }
412 }
413
414 void
415 MidiTrack::non_realtime_locate (framepos_t pos)
416 {
417         Track::non_realtime_locate(pos);
418
419         boost::shared_ptr<MidiPlaylist> playlist = _disk_writer->midi_playlist();
420         if (!playlist) {
421                 return;
422         }
423
424         /* Get the top unmuted region at this position. */
425         boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
426                 playlist->top_unmuted_region_at(pos));
427         if (!region) {
428                 return;
429         }
430
431         /* the source may be missing, but the control still referenced in the GUI */
432         if (!region->midi_source() || !region->model()) {
433                 return;
434         }
435
436         Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
437         if (!lm.locked()) {
438                 return;
439         }
440
441         /* Update track controllers based on its "automation". */
442         const framepos_t     origin = region->position() - region->start();
443         BeatsFramesConverter bfc(_session.tempo_map(), origin);
444         for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
445                 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
446                 boost::shared_ptr<Evoral::Control>        rcontrol;
447                 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
448                     (rcontrol = region->control(tcontrol->parameter()))) {
449                         const Evoral::Beats pos_beats = bfc.from(pos - origin);
450                         if (rcontrol->list()->size() > 0) {
451                                 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
452                         }
453                 }
454         }
455 }
456
457 void
458 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
459 {
460         PortSet& ports (_input->ports());
461
462         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
463
464                 Buffer& b (p->get_buffer (nframes));
465                 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
466                 assert (mb);
467
468                 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
469
470                         const Evoral::Event<framepos_t> ev(*e, false);
471
472                         /* note on, since for step edit, note length is determined
473                            elsewhere
474                         */
475
476                         if (ev.is_note_on()) {
477                                 /* we don't care about the time for this purpose */
478                                 _step_edit_ring_buffer.write (0, ev.event_type(), ev.size(), ev.buffer());
479                         }
480                 }
481         }
482 }
483
484 void
485 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
486 {
487         MidiBuffer& buf (bufs.get_midi (0));
488
489         update_controls (bufs);
490
491         // Append immediate events
492
493         if (_immediate_events.read_space()) {
494
495                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
496                                                             name(), _immediate_events.read_space()));
497
498                 /* write as many of the immediate events as we can, but give "true" as
499                  * the last argument ("stop on overflow in destination") so that we'll
500                  * ship the rest out next time.
501                  *
502                  * the Port::port_offset() + (nframes-1) argument puts all these events at the last
503                  * possible position of the output buffer, so that we do not
504                  * violate monotonicity when writing. Port::port_offset() will
505                  * be non-zero if we're in a split process cycle.
506                  */
507                 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
508         }
509 }
510
511 int
512 MidiTrack::export_stuff (BufferSet&                   buffers,
513                          framepos_t                   start,
514                          framecnt_t                   nframes,
515                          boost::shared_ptr<Processor> endpoint,
516                          bool                         include_endpoint,
517                          bool                         for_export,
518                          bool                         for_freeze)
519 {
520         if (buffers.count().n_midi() == 0) {
521                 return -1;
522         }
523
524         Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
525
526         boost::shared_ptr<MidiPlaylist> mpl = _disk_writer->midi_playlist();
527         if (!mpl) {
528                 return -2;
529         }
530
531         buffers.get_midi(0).clear();
532         if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
533                 return -1;
534         }
535
536         //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
537
538         return 0;
539 }
540
541 boost::shared_ptr<Region>
542 MidiTrack::bounce (InterThreadInfo& itt)
543 {
544         return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
545 }
546
547 boost::shared_ptr<Region>
548 MidiTrack::bounce_range (framepos_t                   start,
549                          framepos_t                   end,
550                          InterThreadInfo&             itt,
551                          boost::shared_ptr<Processor> endpoint,
552                          bool                         include_endpoint)
553 {
554         vector<boost::shared_ptr<Source> > srcs;
555         return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
556 }
557
558 void
559 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
560 {
561         std::cerr << "MIDI freeze currently unsupported" << std::endl;
562 }
563
564 void
565 MidiTrack::unfreeze ()
566 {
567         _freeze_record.state = UnFrozen;
568         FreezeChange (); /* EMIT SIGNAL */
569 }
570
571 void
572 MidiTrack::set_note_mode (NoteMode m)
573 {
574         _note_mode = m;
575         _disk_writer->set_note_mode(m);
576 }
577
578 std::string
579 MidiTrack::describe_parameter (Evoral::Parameter param)
580 {
581         const std::string str(instrument_info().get_controller_name(param));
582         return str.empty() ? Automatable::describe_parameter(param) : str;
583 }
584
585 void
586 MidiTrack::midi_panic()
587 {
588         DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
589         for (uint8_t channel = 0; channel <= 0xF; channel++) {
590                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
591                 write_immediate_event(3, ev);
592                 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
593                 write_immediate_event(3, ev);
594                 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
595                 write_immediate_event(3, ev);
596         }
597 }
598
599 /** \return true on success, false on failure (no buffer space left)
600  */
601 bool
602 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
603 {
604         if (!Evoral::midi_event_is_valid(buf, size)) {
605                 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
606                 return false;
607         }
608         return (_immediate_events.write (0, Evoral::MIDI_EVENT, size, buf) == size);
609 }
610
611 void
612 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
613 {
614         switch (param.type()) {
615         case MidiCCAutomation:
616         case MidiPgmChangeAutomation:
617         case MidiPitchBenderAutomation:
618         case MidiChannelPressureAutomation:
619         case MidiNotePressureAutomation:
620         case MidiSystemExclusiveAutomation:
621                 /* The track control for MIDI parameters is for immediate events to act
622                    as a control surface, write/touch for them is not currently
623                    supported. */
624                 return;
625         default:
626                 Automatable::set_parameter_automation_state(param, state);
627         }
628 }
629
630 void
631 MidiTrack::MidiControl::restore_value ()
632 {
633         actually_set_value (get_value(), Controllable::NoGroup);
634 }
635
636 void
637 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
638 {
639         const Evoral::Parameter &parameter = _list ? _list->parameter() : Control::parameter();
640         const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
641
642         bool valid = false;
643         if (isinf_local(val)) {
644                 cerr << "MIDIControl value is infinity" << endl;
645         } else if (isnan_local(val)) {
646                 cerr << "MIDIControl value is NaN" << endl;
647         } else if (val < desc.lower) {
648                 cerr << "MIDIControl value is < " << desc.lower << endl;
649         } else if (val > desc.upper) {
650                 cerr << "MIDIControl value is > " << desc.upper << endl;
651         } else {
652                 valid = true;
653         }
654
655         if (!valid) {
656                 return;
657         }
658
659         assert(val <= desc.upper);
660         if ( ! _list || ! automation_playback()) {
661                 size_t size = 3;
662                 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
663                 switch(parameter.type()) {
664                 case MidiCCAutomation:
665                         ev[0] += MIDI_CMD_CONTROL;
666                         ev[1] = parameter.id();
667                         ev[2] = int(val);
668                         break;
669
670                 case MidiPgmChangeAutomation:
671                         size = 2;
672                         ev[0] += MIDI_CMD_PGM_CHANGE;
673                         ev[1] = int(val);
674                         break;
675
676                 case MidiChannelPressureAutomation:
677                         size = 2;
678                         ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
679                         ev[1] = int(val);
680                         break;
681
682                 case MidiNotePressureAutomation:
683                         ev[0] += MIDI_CMD_NOTE_PRESSURE;
684                         ev[1] = parameter.id();
685                         ev[2] = int(val);
686                         break;
687
688                 case MidiPitchBenderAutomation:
689                         ev[0] += MIDI_CMD_BENDER;
690                         ev[1] = 0x7F & int(val);
691                         ev[2] = 0x7F & (int(val) >> 7);
692                         break;
693
694                 default:
695                         assert(false);
696                 }
697                 _route->write_immediate_event(size,  ev);
698         }
699
700         AutomationControl::actually_set_value(val, group_override);
701 }
702
703 void
704 MidiTrack::set_step_editing (bool yn)
705 {
706         if (_session.record_status() != Session::Disabled) {
707                 return;
708         }
709
710         if (yn != _step_editing) {
711                 _step_editing = yn;
712                 StepEditStatusChange (yn);
713         }
714 }
715
716 boost::shared_ptr<SMFSource>
717 MidiTrack::write_source (uint32_t)
718 {
719         return _disk_writer->midi_write_source ();
720 }
721
722 void
723 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
724 {
725         if (_playback_filter.set_channel_mode(mode, mask)) {
726                 _session.set_dirty();
727         }
728 }
729
730 void
731 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
732 {
733         if (_capture_filter.set_channel_mode(mode, mask)) {
734                 _session.set_dirty();
735         }
736 }
737
738 void
739 MidiTrack::set_playback_channel_mask (uint16_t mask)
740 {
741         if (_playback_filter.set_channel_mask(mask)) {
742                 _session.set_dirty();
743         }
744 }
745
746 void
747 MidiTrack::set_capture_channel_mask (uint16_t mask)
748 {
749         if (_capture_filter.set_channel_mask(mask)) {
750                 _session.set_dirty();
751         }
752 }
753
754 boost::shared_ptr<MidiPlaylist>
755 MidiTrack::midi_playlist ()
756 {
757         return boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
758 }
759
760 bool
761 MidiTrack::input_active () const
762 {
763         return _input_active;
764 }
765
766 void
767 MidiTrack::set_input_active (bool yn)
768 {
769         if (yn != _input_active) {
770                 _input_active = yn;
771                 map_input_active (yn);
772                 InputActiveChanged (); /* EMIT SIGNAL */
773         }
774 }
775
776 void
777 MidiTrack::map_input_active (bool yn)
778 {
779         if (!_input) {
780                 return;
781         }
782
783         PortSet& ports (_input->ports());
784
785         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
786                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
787                 if (yn != mp->input_active()) {
788                         mp->set_input_active (yn);
789                 }
790         }
791 }
792
793 void
794 MidiTrack::track_input_active (IOChange change, void* /* src */)
795 {
796         if (change.type & IOChange::ConfigurationChanged) {
797                 map_input_active (_input_active);
798         }
799 }
800
801 boost::shared_ptr<MidiBuffer>
802 MidiTrack::get_gui_feed_buffer () const
803 {
804         return _disk_reader->get_gui_feed_buffer ();
805 }
806
807 void
808 MidiTrack::act_on_mute ()
809 {
810         /* this is called right after our mute status has changed.
811            if we are now muted, send suitable output to shutdown
812            all our notes.
813
814            XXX we should should also stop all relevant note trackers.
815         */
816
817         /* If we haven't got a diskstream yet, there's nothing to worry about,
818            and we can't call get_channel_mask() anyway.
819         */
820         if (!_disk_writer) {
821                 return;
822         }
823
824         if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
825                 /* only send messages for channels we are using */
826
827                 uint16_t mask = _playback_filter.get_channel_mask();
828
829                 for (uint8_t channel = 0; channel <= 0xF; channel++) {
830
831                         if ((1<<channel) & mask) {
832
833                                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
834                                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
835                                 write_immediate_event (3, ev);
836
837                                 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
838                                    silence notes that came from another non-muted track. */
839                         }
840                 }
841
842                 /* Resolve active notes. */
843                 _disk_reader->resolve_tracker(_immediate_events, Port::port_offset());
844         }
845 }
846
847 void
848 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
849 {
850         Track::monitoring_changed (self, gcd);
851
852         /* monitoring state changed, so flush out any on notes at the
853          * port level.
854          */
855
856         PortSet& ports (_output->ports());
857
858         for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
859                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
860                 if (mp) {
861                         mp->require_resolve ();
862                 }
863         }
864
865         _disk_reader->reset_tracker ();
866 }
867
868 MonitorState
869 MidiTrack::monitoring_state () const
870 {
871         MonitorState ms = Track::monitoring_state();
872         if (ms == MonitoringSilence) {
873                 return MonitoringInput;
874         }
875         return ms;
876 }