2 Copyright (C) 2006 Paul Davis
3 Author: David Robillard
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.
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.
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.
20 #include "pbd/enumwriter.h"
21 #include "pbd/convert.h"
22 #include "evoral/midi_util.h"
24 #include "ardour/buffer_set.h"
25 #include "ardour/debug.h"
26 #include "ardour/delivery.h"
27 #include "ardour/meter.h"
28 #include "ardour/midi_diskstream.h"
29 #include "ardour/midi_playlist.h"
30 #include "ardour/midi_port.h"
31 #include "ardour/midi_track.h"
32 #include "ardour/port.h"
33 #include "ardour/processor.h"
34 #include "ardour/session.h"
35 #include "ardour/session_playlists.h"
36 #include "ardour/utils.h"
41 class InterThreadInfo;
48 using namespace ARDOUR;
51 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
52 : Track (sess, name, flag, mode, DataType::MIDI)
53 , _immediate_events(1024) // FIXME: size?
54 , _step_edit_ring_buffer(64) // FIXME: size?
55 , _note_mode(Sustained)
56 , _step_editing (false)
57 , _input_active (true)
61 MidiTrack::~MidiTrack ()
72 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
77 boost::shared_ptr<Diskstream>
78 MidiTrack::create_diskstream ()
80 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
82 if (_flags & Hidden) {
83 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
85 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
88 assert(_mode != Destructive);
90 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
95 MidiTrack::set_record_enabled (bool yn, void *src)
101 Track::set_record_enabled (yn, src);
105 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
107 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
108 and the diskstream must be set up to fill its buffers using the correct _note_mode.
110 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
111 mds->set_note_mode (_note_mode);
113 Track::set_diskstream (ds);
115 mds->reset_tracker ();
117 _diskstream->set_track (this);
118 _diskstream->set_destructive (_mode == Destructive);
119 _diskstream->set_record_enabled (false);
121 _diskstream_data_recorded_connection.disconnect ();
122 mds->DataRecorded.connect_same_thread (
123 _diskstream_data_recorded_connection,
124 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
126 DiskstreamChanged (); /* EMIT SIGNAL */
129 boost::shared_ptr<MidiDiskstream>
130 MidiTrack::midi_diskstream() const
132 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
136 MidiTrack::set_state (const XMLNode& node, int version)
138 const XMLProperty *prop;
140 /* This must happen before Track::set_state(), as there will be a buffer
141 fill during that call, and we must fill buffers using the correct
144 if ((prop = node.property (X_("note-mode"))) != 0) {
145 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
147 _note_mode = Sustained;
150 if (Track::set_state (node, version)) {
154 // No destructive MIDI tracks (yet?)
157 if ((prop = node.property ("input-active")) != 0) {
158 set_input_active (string_is_affirmative (prop->value()));
161 pending_state = const_cast<XMLNode*> (&node);
163 if (_session.state_of_the_state() & Session::Loading) {
164 _session.StateReady.connect_same_thread (
165 *this, boost::bind (&MidiTrack::set_state_part_two, this));
167 set_state_part_two ();
174 MidiTrack::state(bool full_state)
176 XMLNode& root (Track::state(full_state));
177 XMLNode* freeze_node;
180 if (_freeze_record.playlist) {
183 freeze_node = new XMLNode (X_("freeze-info"));
184 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
185 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
187 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
188 inode = new XMLNode (X_("processor"));
189 (*i)->id.print (buf, sizeof(buf));
190 inode->add_property (X_("id"), buf);
191 inode->add_child_copy ((*i)->state);
193 freeze_node->add_child_nocopy (*inode);
196 root.add_child_nocopy (*freeze_node);
199 root.add_property (X_("note-mode"), enum_2_string (_note_mode));
201 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
202 root.add_property ("note-mode", enum_2_string (_note_mode));
203 root.add_property ("input-active", (_input_active ? "yes" : "no"));
209 MidiTrack::set_state_part_two ()
213 LocaleGuard lg (X_("POSIX"));
215 /* This is called after all session state has been restored but before
216 have been made ports and connections are established.
219 if (pending_state == 0) {
223 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
225 _freeze_record.state = Frozen;
227 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
230 _freeze_record.processor_info.clear ();
232 if ((prop = fnode->property (X_("playlist"))) != 0) {
233 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
235 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
237 _freeze_record.playlist.reset();
238 _freeze_record.state = NoFreeze;
243 if ((prop = fnode->property (X_("state"))) != 0) {
244 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
247 XMLNodeConstIterator citer;
248 XMLNodeList clist = fnode->children();
250 for (citer = clist.begin(); citer != clist.end(); ++citer) {
251 if ((*citer)->name() != X_("processor")) {
255 if ((prop = (*citer)->property (X_("id"))) == 0) {
259 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
260 boost::shared_ptr<Processor>());
261 frii->id = prop->value ();
262 _freeze_record.processor_info.push_back (frii);
266 if (midi_diskstream ()) {
267 midi_diskstream()->set_block_size (_session.get_block_size ());
273 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
277 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
279 Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
284 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
286 automation_snapshot (start_frame);
288 if (n_outputs().n_total() == 0 && _processors.empty()) {
297 framepos_t transport_frame = _session.transport_frame();
300 framecnt_t playback_distance;
302 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
303 /* need to do this so that the diskstream sets its
304 playback distance to zero, thus causing diskstream::commit
307 dret = diskstream->process (transport_frame, 0, playback_distance);
308 need_butler = diskstream->commit (playback_distance);
314 if ((dret = diskstream->process (transport_frame, nframes, playback_distance)) != 0) {
315 need_butler = diskstream->commit (playback_distance);
320 /* special condition applies */
322 if (_meter_point == MeterInput) {
323 _input->process_input (_meter, start_frame, end_frame, nframes);
326 if (monitoring_state() == MonitoringInput) {
328 /* not actually recording, but we want to hear the input material anyway,
329 at least potentially (depending on monitoring options)
332 passthru (start_frame, end_frame, nframes, 0);
336 XXX is it true that the earlier test on n_outputs()
337 means that we can avoid checking it again here? i think
338 so, because changing the i/o configuration of an IO
339 requires holding the AudioEngine lock, which we hold
340 while in the process() tree.
344 /* copy the diskstream data to all output buffers */
346 //const size_t limit = n_process_buffers().n_audio();
347 BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
348 MidiBuffer& mbuf (bufs.get_midi (0));
350 /* we are a MIDI track, so we always start the chain with a single-channel diskstream */
356 diskstream->get_playback (mbuf, nframes);
358 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
360 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
362 /* final argument: don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
364 process_output_buffers (
365 bufs, start_frame, end_frame, nframes,
366 declick, (!diskstream->record_enabled() && !_session.transport_stopped())
370 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
371 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
373 d->flush_buffers (nframes);
377 need_butler = diskstream->commit (playback_distance);
383 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
385 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
387 if (ret == 0 && _step_editing) {
388 push_midi_input_to_step_edit_ringbuffer (nframes);
395 MidiTrack::realtime_locate ()
397 Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
403 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
404 (*i)->realtime_locate ();
407 midi_diskstream()->reset_tracker ();
411 MidiTrack::realtime_handle_transport_stopped ()
413 Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
419 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
420 (*i)->realtime_handle_transport_stopped ();
425 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
427 PortSet& ports (_input->ports());
429 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
431 Buffer& b (p->get_buffer (nframes));
432 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
435 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
437 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
439 /* note on, since for step edit, note length is determined
443 if (ev.is_note_on()) {
444 /* we don't care about the time for this purpose */
445 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
452 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
454 MidiBuffer& buf (bufs.get_midi (0));
456 // Append immediate events
458 if (_immediate_events.read_space()) {
460 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
461 name(), _immediate_events.read_space()));
463 /* write as many of the immediate events as we can, but give "true" as
464 * the last argument ("stop on overflow in destination") so that we'll
465 * ship the rest out next time.
467 * the (nframes-1) argument puts all these events at the last
468 * possible position of the output buffer, so that we do not
469 * violate monotonicity when writing.
472 _immediate_events.read (buf, 0, 1, nframes-1, true);
477 MidiTrack::export_stuff (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framecnt_t /*nframes*/,
478 boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/, bool /*forexport*/)
483 boost::shared_ptr<Region>
484 MidiTrack::bounce (InterThreadInfo& /*itt*/)
486 std::cerr << "MIDI bounce currently unsupported" << std::endl;
487 return boost::shared_ptr<Region> ();
491 boost::shared_ptr<Region>
492 MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/,
493 boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/)
495 std::cerr << "MIDI bounce range currently unsupported" << std::endl;
496 return boost::shared_ptr<Region> ();
500 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
502 std::cerr << "MIDI freeze currently unsupported" << std::endl;
506 MidiTrack::unfreeze ()
508 _freeze_record.state = UnFrozen;
509 FreezeChange (); /* EMIT SIGNAL */
513 MidiTrack::set_note_mode (NoteMode m)
516 midi_diskstream()->set_note_mode(m);
520 MidiTrack::midi_panic()
522 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
523 for (uint8_t channel = 0; channel <= 0xF; channel++) {
524 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
525 write_immediate_event(3, ev);
526 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
527 write_immediate_event(3, ev);
528 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
529 write_immediate_event(3, ev);
533 /** \return true on success, false on failure (no buffer space left)
536 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
538 if (!Evoral::midi_event_is_valid(buf, size)) {
539 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
542 const uint32_t type = EventTypeMap::instance().midi_event_type(buf[0]);
543 return (_immediate_events.write(0, type, size, buf) == size);
547 MidiTrack::MidiControl::set_value(double val)
550 if (std::isinf(val)) {
551 cerr << "MIDIControl value is infinity" << endl;
552 } else if (std::isnan(val)) {
553 cerr << "MIDIControl value is NaN" << endl;
554 } else if (val < _list->parameter().min()) {
555 cerr << "MIDIControl value is < " << _list->parameter().min() << endl;
556 } else if (val > _list->parameter().max()) {
557 cerr << "MIDIControl value is > " << _list->parameter().max() << endl;
566 assert(val <= _list->parameter().max());
567 if ( ! automation_playback()) {
569 uint8_t ev[3] = { _list->parameter().channel(), uint8_t (val), 0 };
570 switch(_list->parameter().type()) {
571 case MidiCCAutomation:
572 ev[0] += MIDI_CMD_CONTROL;
573 ev[1] = _list->parameter().id();
577 case MidiPgmChangeAutomation:
579 ev[0] += MIDI_CMD_PGM_CHANGE;
583 case MidiChannelPressureAutomation:
585 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
589 case MidiPitchBenderAutomation:
590 ev[0] += MIDI_CMD_BENDER;
591 ev[1] = 0x7F & int(val);
592 ev[2] = 0x7F & (int(val) >> 7);
598 _route->write_immediate_event(size, ev);
601 AutomationControl::set_value(val);
605 MidiTrack::set_step_editing (bool yn)
607 if (_session.record_status() != Session::Disabled) {
611 if (yn != _step_editing) {
613 StepEditStatusChange (yn);
617 boost::shared_ptr<SMFSource>
618 MidiTrack::write_source (uint32_t)
620 return midi_diskstream()->write_source ();
624 MidiTrack::set_channel_mode (ChannelMode mode, uint16_t mask)
626 midi_diskstream()->set_channel_mode (mode, mask);
630 MidiTrack::get_channel_mode ()
632 return midi_diskstream()->get_channel_mode ();
636 MidiTrack::get_channel_mask ()
638 return midi_diskstream()->get_channel_mask ();
641 boost::shared_ptr<MidiPlaylist>
642 MidiTrack::midi_playlist ()
644 return midi_diskstream()->midi_playlist ();
648 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
650 DataRecorded (src); /* EMIT SIGNAL */
654 MidiTrack::input_active () const
656 return _input_active;
660 MidiTrack::set_input_active (bool yn)
662 if (yn != _input_active) {
664 map_input_active (yn);
665 InputActiveChanged (); /* EMIT SIGNAL */
670 MidiTrack::map_input_active (bool yn)
676 PortSet& ports (_input->ports());
678 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
679 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
680 if (yn != mp->input_active()) {
681 mp->set_input_active (yn);
687 MidiTrack::track_input_active (IOChange change, void* /* src */)
689 if (change.type & IOChange::ConfigurationChanged) {
690 map_input_active (_input_active);
694 boost::shared_ptr<Diskstream>
695 MidiTrack::diskstream_factory (XMLNode const & node)
697 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
700 boost::shared_ptr<MidiBuffer>
701 MidiTrack::get_gui_feed_buffer () const
703 return midi_diskstream()->get_gui_feed_buffer ();
707 MidiTrack::act_on_mute ()
709 /* this is called right after our mute status has changed.
710 if we are now muted, send suitable output to shutdown
713 XXX we should should also stop all relevant note trackers.
717 /* only send messages for channels we are using */
719 uint16_t mask = get_channel_mask();
721 for (uint8_t channel = 0; channel <= 0xF; channel++) {
723 if ((1<<channel) & mask) {
725 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
726 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
727 write_immediate_event (3, ev);
728 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
729 write_immediate_event (3, ev);
736 MidiTrack::set_monitoring (MonitorChoice mc)
738 Track::set_monitoring (mc);
740 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
743 md->reset_tracker ();
748 MidiTrack::monitoring_state () const
750 /* Explicit requests */
752 if (_monitoring & MonitorInput) {
753 return MonitoringInput;
756 if (_monitoring & MonitorDisk) {
757 return MonitoringDisk;
760 if (_session.transport_rolling()) {
761 return MonitoringDisk;
764 /* the return value here doesn't mean that we're actually monitoring
765 * input, let alone input *audio*. but it means that we are NOT
766 * monitoring silence. this allows us to still hear any audio generated
767 * by using internal generation techniques
770 return MonitoringInput;