remove debug output
[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         if (_disk_reader->need_butler() || _disk_writer->need_butler()) {
367                 need_butler = true;
368         }
369
370         flush_processor_buffers_locked (nframes);
371
372         return 0;
373 }
374
375 int
376 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
377 {
378         int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
379
380         if (ret == 0 && _step_editing) {
381                 push_midi_input_to_step_edit_ringbuffer (nframes);
382         }
383
384         return ret;
385 }
386
387 void
388 MidiTrack::realtime_locate ()
389 {
390         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
391
392         if (!lm.locked ()) {
393                 return;
394         }
395
396         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
397                 (*i)->realtime_locate ();
398         }
399
400         _disk_reader->reset_tracker ();
401 }
402
403 void
404 MidiTrack::non_realtime_locate (framepos_t pos)
405 {
406         Track::non_realtime_locate(pos);
407
408         boost::shared_ptr<MidiPlaylist> playlist = _disk_writer->midi_playlist();
409         if (!playlist) {
410                 return;
411         }
412
413         /* Get the top unmuted region at this position. */
414         boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
415                 playlist->top_unmuted_region_at(pos));
416         if (!region) {
417                 return;
418         }
419
420         /* the source may be missing, but the control still referenced in the GUI */
421         if (!region->midi_source() || !region->model()) {
422                 return;
423         }
424
425         Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
426         if (!lm.locked()) {
427                 return;
428         }
429
430         /* Update track controllers based on its "automation". */
431         const framepos_t     origin = region->position() - region->start();
432         BeatsFramesConverter bfc(_session.tempo_map(), origin);
433         for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
434                 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
435                 boost::shared_ptr<Evoral::Control>        rcontrol;
436                 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
437                     (rcontrol = region->control(tcontrol->parameter()))) {
438                         const Evoral::Beats pos_beats = bfc.from(pos - origin);
439                         if (rcontrol->list()->size() > 0) {
440                                 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
441                         }
442                 }
443         }
444 }
445
446 void
447 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
448 {
449         PortSet& ports (_input->ports());
450
451         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
452
453                 Buffer& b (p->get_buffer (nframes));
454                 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
455                 assert (mb);
456
457                 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
458
459                         const Evoral::Event<framepos_t> ev(*e, false);
460
461                         /* note on, since for step edit, note length is determined
462                            elsewhere
463                         */
464
465                         if (ev.is_note_on()) {
466                                 /* we don't care about the time for this purpose */
467                                 _step_edit_ring_buffer.write (0, ev.event_type(), ev.size(), ev.buffer());
468                         }
469                 }
470         }
471 }
472
473 void
474 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
475 {
476         MidiBuffer& buf (bufs.get_midi (0));
477
478         update_controls (bufs);
479
480         // Append immediate events
481
482         if (_immediate_events.read_space()) {
483
484                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
485                                                             name(), _immediate_events.read_space()));
486
487                 /* write as many of the immediate events as we can, but give "true" as
488                  * the last argument ("stop on overflow in destination") so that we'll
489                  * ship the rest out next time.
490                  *
491                  * the Port::port_offset() + (nframes-1) argument puts all these events at the last
492                  * possible position of the output buffer, so that we do not
493                  * violate monotonicity when writing. Port::port_offset() will
494                  * be non-zero if we're in a split process cycle.
495                  */
496                 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
497         }
498 }
499
500 int
501 MidiTrack::export_stuff (BufferSet&                   buffers,
502                          framepos_t                   start,
503                          framecnt_t                   nframes,
504                          boost::shared_ptr<Processor> endpoint,
505                          bool                         include_endpoint,
506                          bool                         for_export,
507                          bool                         for_freeze)
508 {
509         if (buffers.count().n_midi() == 0) {
510                 return -1;
511         }
512
513         Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
514
515         boost::shared_ptr<MidiPlaylist> mpl = _disk_writer->midi_playlist();
516         if (!mpl) {
517                 return -2;
518         }
519
520         buffers.get_midi(0).clear();
521         if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
522                 return -1;
523         }
524
525         //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
526
527         return 0;
528 }
529
530 boost::shared_ptr<Region>
531 MidiTrack::bounce (InterThreadInfo& itt)
532 {
533         return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
534 }
535
536 boost::shared_ptr<Region>
537 MidiTrack::bounce_range (framepos_t                   start,
538                          framepos_t                   end,
539                          InterThreadInfo&             itt,
540                          boost::shared_ptr<Processor> endpoint,
541                          bool                         include_endpoint)
542 {
543         vector<boost::shared_ptr<Source> > srcs;
544         return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
545 }
546
547 void
548 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
549 {
550         std::cerr << "MIDI freeze currently unsupported" << std::endl;
551 }
552
553 void
554 MidiTrack::unfreeze ()
555 {
556         _freeze_record.state = UnFrozen;
557         FreezeChange (); /* EMIT SIGNAL */
558 }
559
560 void
561 MidiTrack::set_note_mode (NoteMode m)
562 {
563         _note_mode = m;
564         _disk_writer->set_note_mode(m);
565 }
566
567 std::string
568 MidiTrack::describe_parameter (Evoral::Parameter param)
569 {
570         const std::string str(instrument_info().get_controller_name(param));
571         return str.empty() ? Automatable::describe_parameter(param) : str;
572 }
573
574 void
575 MidiTrack::midi_panic()
576 {
577         DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
578         for (uint8_t channel = 0; channel <= 0xF; channel++) {
579                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
580                 write_immediate_event(3, ev);
581                 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
582                 write_immediate_event(3, ev);
583                 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
584                 write_immediate_event(3, ev);
585         }
586 }
587
588 /** \return true on success, false on failure (no buffer space left)
589  */
590 bool
591 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
592 {
593         if (!Evoral::midi_event_is_valid(buf, size)) {
594                 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
595                 return false;
596         }
597         return (_immediate_events.write (0, Evoral::MIDI_EVENT, size, buf) == size);
598 }
599
600 void
601 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
602 {
603         switch (param.type()) {
604         case MidiCCAutomation:
605         case MidiPgmChangeAutomation:
606         case MidiPitchBenderAutomation:
607         case MidiChannelPressureAutomation:
608         case MidiNotePressureAutomation:
609         case MidiSystemExclusiveAutomation:
610                 /* The track control for MIDI parameters is for immediate events to act
611                    as a control surface, write/touch for them is not currently
612                    supported. */
613                 return;
614         default:
615                 Automatable::set_parameter_automation_state(param, state);
616         }
617 }
618
619 void
620 MidiTrack::MidiControl::restore_value ()
621 {
622         actually_set_value (get_value(), Controllable::NoGroup);
623 }
624
625 void
626 MidiTrack::MidiControl::actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
627 {
628         const Evoral::Parameter &parameter = _list ? _list->parameter() : Control::parameter();
629         const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
630
631         bool valid = false;
632         if (isinf_local(val)) {
633                 cerr << "MIDIControl value is infinity" << endl;
634         } else if (isnan_local(val)) {
635                 cerr << "MIDIControl value is NaN" << endl;
636         } else if (val < desc.lower) {
637                 cerr << "MIDIControl value is < " << desc.lower << endl;
638         } else if (val > desc.upper) {
639                 cerr << "MIDIControl value is > " << desc.upper << endl;
640         } else {
641                 valid = true;
642         }
643
644         if (!valid) {
645                 return;
646         }
647
648         assert(val <= desc.upper);
649         if ( ! _list || ! automation_playback()) {
650                 size_t size = 3;
651                 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
652                 switch(parameter.type()) {
653                 case MidiCCAutomation:
654                         ev[0] += MIDI_CMD_CONTROL;
655                         ev[1] = parameter.id();
656                         ev[2] = int(val);
657                         break;
658
659                 case MidiPgmChangeAutomation:
660                         size = 2;
661                         ev[0] += MIDI_CMD_PGM_CHANGE;
662                         ev[1] = int(val);
663                         break;
664
665                 case MidiChannelPressureAutomation:
666                         size = 2;
667                         ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
668                         ev[1] = int(val);
669                         break;
670
671                 case MidiNotePressureAutomation:
672                         ev[0] += MIDI_CMD_NOTE_PRESSURE;
673                         ev[1] = parameter.id();
674                         ev[2] = int(val);
675                         break;
676
677                 case MidiPitchBenderAutomation:
678                         ev[0] += MIDI_CMD_BENDER;
679                         ev[1] = 0x7F & int(val);
680                         ev[2] = 0x7F & (int(val) >> 7);
681                         break;
682
683                 default:
684                         assert(false);
685                 }
686                 _route->write_immediate_event(size,  ev);
687         }
688
689         AutomationControl::actually_set_value(val, group_override);
690 }
691
692 void
693 MidiTrack::set_step_editing (bool yn)
694 {
695         if (_session.record_status() != Session::Disabled) {
696                 return;
697         }
698
699         if (yn != _step_editing) {
700                 _step_editing = yn;
701                 StepEditStatusChange (yn);
702         }
703 }
704
705 boost::shared_ptr<SMFSource>
706 MidiTrack::write_source (uint32_t)
707 {
708         return _disk_writer->midi_write_source ();
709 }
710
711 void
712 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
713 {
714         if (_playback_filter.set_channel_mode(mode, mask)) {
715                 _session.set_dirty();
716         }
717 }
718
719 void
720 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
721 {
722         if (_capture_filter.set_channel_mode(mode, mask)) {
723                 _session.set_dirty();
724         }
725 }
726
727 void
728 MidiTrack::set_playback_channel_mask (uint16_t mask)
729 {
730         if (_playback_filter.set_channel_mask(mask)) {
731                 _session.set_dirty();
732         }
733 }
734
735 void
736 MidiTrack::set_capture_channel_mask (uint16_t mask)
737 {
738         if (_capture_filter.set_channel_mask(mask)) {
739                 _session.set_dirty();
740         }
741 }
742
743 boost::shared_ptr<MidiPlaylist>
744 MidiTrack::midi_playlist ()
745 {
746         return boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
747 }
748
749 bool
750 MidiTrack::input_active () const
751 {
752         return _input_active;
753 }
754
755 void
756 MidiTrack::set_input_active (bool yn)
757 {
758         if (yn != _input_active) {
759                 _input_active = yn;
760                 map_input_active (yn);
761                 InputActiveChanged (); /* EMIT SIGNAL */
762         }
763 }
764
765 void
766 MidiTrack::map_input_active (bool yn)
767 {
768         if (!_input) {
769                 return;
770         }
771
772         PortSet& ports (_input->ports());
773
774         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
775                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
776                 if (yn != mp->input_active()) {
777                         mp->set_input_active (yn);
778                 }
779         }
780 }
781
782 void
783 MidiTrack::track_input_active (IOChange change, void* /* src */)
784 {
785         if (change.type & IOChange::ConfigurationChanged) {
786                 map_input_active (_input_active);
787         }
788 }
789
790 boost::shared_ptr<MidiBuffer>
791 MidiTrack::get_gui_feed_buffer () const
792 {
793         return _disk_reader->get_gui_feed_buffer ();
794 }
795
796 void
797 MidiTrack::act_on_mute ()
798 {
799         /* this is called right after our mute status has changed.
800            if we are now muted, send suitable output to shutdown
801            all our notes.
802
803            XXX we should should also stop all relevant note trackers.
804         */
805
806         /* If we haven't got a diskstream yet, there's nothing to worry about,
807            and we can't call get_channel_mask() anyway.
808         */
809         if (!_disk_writer) {
810                 return;
811         }
812
813         if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
814                 /* only send messages for channels we are using */
815
816                 uint16_t mask = _playback_filter.get_channel_mask();
817
818                 for (uint8_t channel = 0; channel <= 0xF; channel++) {
819
820                         if ((1<<channel) & mask) {
821
822                                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
823                                 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
824                                 write_immediate_event (3, ev);
825
826                                 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
827                                    silence notes that came from another non-muted track. */
828                         }
829                 }
830
831                 /* Resolve active notes. */
832                 _disk_reader->resolve_tracker(_immediate_events, Port::port_offset());
833         }
834 }
835
836 void
837 MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
838 {
839         Track::monitoring_changed (self, gcd);
840
841         /* monitoring state changed, so flush out any on notes at the
842          * port level.
843          */
844
845         PortSet& ports (_output->ports());
846
847         for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
848                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
849                 if (mp) {
850                         mp->require_resolve ();
851                 }
852         }
853
854         _disk_reader->reset_tracker ();
855 }
856
857 MonitorState
858 MidiTrack::monitoring_state () const
859 {
860         MonitorState ms = Track::monitoring_state();
861         if (ms == MonitoringSilence) {
862                 return MonitoringInput;
863         }
864         return ms;
865 }