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