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