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