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