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