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/error.h"
22 #include "pbd/enumwriter.h"
23 #include "pbd/convert.h"
24 #include "midi++/events.h"
25 #include "evoral/midi_util.h"
27 #include "ardour/amp.h"
28 #include "ardour/buffer_set.h"
29 #include "ardour/debug.h"
30 #include "ardour/delivery.h"
31 #include "ardour/io_processor.h"
32 #include "ardour/meter.h"
33 #include "ardour/midi_diskstream.h"
34 #include "ardour/midi_playlist.h"
35 #include "ardour/midi_port.h"
36 #include "ardour/midi_region.h"
37 #include "ardour/midi_source.h"
38 #include "ardour/midi_track.h"
39 #include "ardour/panner.h"
40 #include "ardour/port.h"
41 #include "ardour/processor.h"
42 #include "ardour/route_group_specialized.h"
43 #include "ardour/session.h"
44 #include "ardour/session_playlists.h"
45 #include "ardour/utils.h"
50 using namespace ARDOUR
;
53 MidiTrack::MidiTrack (Session
& sess
, string name
, Route::Flag flag
, TrackMode mode
)
54 : Track (sess
, name
, flag
, mode
, DataType::MIDI
)
55 , _immediate_events(1024) // FIXME: size?
56 , _step_edit_ring_buffer(64) // FIXME: size?
57 , _note_mode(Sustained
)
58 , _step_editing (false)
59 , _default_channel (0)
64 MidiTrack::~MidiTrack ()
69 MidiTrack::use_new_diskstream ()
71 MidiDiskstream::Flag dflags
= MidiDiskstream::Flag (0);
73 if (_flags
& Hidden
) {
74 dflags
= MidiDiskstream::Flag (dflags
| MidiDiskstream::Hidden
);
76 dflags
= MidiDiskstream::Flag (dflags
| MidiDiskstream::Recordable
);
79 assert(_mode
!= Destructive
);
81 boost::shared_ptr
<MidiDiskstream
> ds (new MidiDiskstream (_session
, name(), dflags
));
82 ds
->do_refill_with_alloc ();
83 ds
->set_block_size (_session
.get_block_size ());
89 MidiTrack::set_record_enabled (bool yn
, void *src
)
95 Track::set_record_enabled (yn
, src
);
99 MidiTrack::set_diskstream (boost::shared_ptr
<Diskstream
> ds
)
101 Track::set_diskstream (ds
);
103 _diskstream
->set_track (this);
104 _diskstream
->set_destructive (_mode
== Destructive
);
106 _diskstream
->set_record_enabled (false);
107 //_diskstream->monitor_input (false);
109 _diskstream_data_recorded_connection
.disconnect ();
110 boost::shared_ptr
<MidiDiskstream
> mds
= boost::dynamic_pointer_cast
<MidiDiskstream
> (ds
);
111 mds
->DataRecorded
.connect_same_thread (
112 _diskstream_data_recorded_connection
,
113 boost::bind (&MidiTrack::diskstream_data_recorded
, this, _1
, _2
));
115 DiskstreamChanged (); /* EMIT SIGNAL */
118 boost::shared_ptr
<MidiDiskstream
>
119 MidiTrack::midi_diskstream() const
121 return boost::dynamic_pointer_cast
<MidiDiskstream
>(_diskstream
);
125 MidiTrack::set_state (const XMLNode
& node
, int version
)
127 return _set_state (node
, version
, true);
131 MidiTrack::_set_state (const XMLNode
& node
, int version
, bool call_base
)
133 const XMLProperty
*prop
;
134 XMLNodeConstIterator iter
;
136 if (Route::_set_state (node
, version
, call_base
)) {
140 // No destructive MIDI tracks (yet?)
143 if ((prop
= node
.property (X_("note-mode"))) != 0) {
144 _note_mode
= NoteMode (string_2_enum (prop
->value(), _note_mode
));
146 _note_mode
= Sustained
;
149 if ((prop
= node
.property ("midi-thru")) != 0) {
150 set_midi_thru (prop
->value() == "yes");
153 if ((prop
= node
.property ("default-channel")) != 0) {
154 set_default_channel ((uint8_t) atoi (prop
->value()));
158 XMLNodeConstIterator niter
;
161 nlist
= node
.children();
163 if (version
>= 3000) {
164 if ((child
= find_named_node (node
, X_("Diskstream"))) != 0) {
165 boost::shared_ptr
<MidiDiskstream
> ds (new MidiDiskstream (_session
, *child
));
166 ds
->do_refill_with_alloc ();
171 /* set rec-enable control *AFTER* setting up diskstream, because it may
172 want to operate on the diskstream as it sets its own state
175 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
){
178 if (child
->name() == Controllable::xml_node_name
&& (prop
= child
->property ("name")) != 0) {
179 if (prop
->value() == X_("recenable")) {
180 _rec_enable_control
->set_state (*child
, version
);
185 pending_state
= const_cast<XMLNode
*> (&node
);
187 if (_session
.state_of_the_state() & Session::Loading
) {
188 _session
.StateReady
.connect_same_thread (
189 *this, boost::bind (&MidiTrack::set_state_part_two
, this));
191 set_state_part_two ();
198 MidiTrack::state(bool full_state
)
200 XMLNode
& root (Route::state(full_state
));
201 XMLNode
* freeze_node
;
204 if (_freeze_record
.playlist
) {
207 freeze_node
= new XMLNode (X_("freeze-info"));
208 freeze_node
->add_property ("playlist", _freeze_record
.playlist
->name());
209 freeze_node
->add_property ("state", enum_2_string (_freeze_record
.state
));
211 for (vector
<FreezeRecordProcessorInfo
*>::iterator i
= _freeze_record
.processor_info
.begin(); i
!= _freeze_record
.processor_info
.end(); ++i
) {
212 inode
= new XMLNode (X_("processor"));
213 (*i
)->id
.print (buf
, sizeof(buf
));
214 inode
->add_property (X_("id"), buf
);
215 inode
->add_child_copy ((*i
)->state
);
217 freeze_node
->add_child_nocopy (*inode
);
220 root
.add_child_nocopy (*freeze_node
);
223 root
.add_property (X_("note-mode"), enum_2_string (_note_mode
));
224 root
.add_child_nocopy (_rec_enable_control
->get_state());
225 root
.add_child_nocopy (_diskstream
->get_state ());
227 root
.add_property ("step-editing", (_step_editing
? "yes" : "no"));
228 root
.add_property ("note-mode", enum_2_string (_note_mode
));
229 root
.add_property ("midi-thru", (_midi_thru
? "yes" : "no"));
230 snprintf (buf
, sizeof (buf
), "%d", (int) _default_channel
);
231 root
.add_property ("default-channel", buf
);
237 MidiTrack::set_state_part_two ()
241 LocaleGuard
lg (X_("POSIX"));
243 /* This is called after all session state has been restored but before
244 have been made ports and connections are established.
247 if (pending_state
== 0) {
251 if ((fnode
= find_named_node (*pending_state
, X_("freeze-info"))) != 0) {
253 _freeze_record
.state
= Frozen
;
255 for (vector
<FreezeRecordProcessorInfo
*>::iterator i
= _freeze_record
.processor_info
.begin(); i
!= _freeze_record
.processor_info
.end(); ++i
) {
258 _freeze_record
.processor_info
.clear ();
260 if ((prop
= fnode
->property (X_("playlist"))) != 0) {
261 boost::shared_ptr
<Playlist
> pl
= _session
.playlists
->by_name (prop
->value());
263 _freeze_record
.playlist
= boost::dynamic_pointer_cast
<MidiPlaylist
> (pl
);
265 _freeze_record
.playlist
.reset();
266 _freeze_record
.state
= NoFreeze
;
271 if ((prop
= fnode
->property (X_("state"))) != 0) {
272 _freeze_record
.state
= FreezeState (string_2_enum (prop
->value(), _freeze_record
.state
));
275 XMLNodeConstIterator citer
;
276 XMLNodeList clist
= fnode
->children();
278 for (citer
= clist
.begin(); citer
!= clist
.end(); ++citer
) {
279 if ((*citer
)->name() != X_("processor")) {
283 if ((prop
= (*citer
)->property (X_("id"))) == 0) {
287 FreezeRecordProcessorInfo
* frii
= new FreezeRecordProcessorInfo (*((*citer
)->children().front()),
288 boost::shared_ptr
<Processor
>());
289 frii
->id
= prop
->value ();
290 _freeze_record
.processor_info
.push_back (frii
);
294 if (midi_diskstream ()) {
295 midi_diskstream()->set_block_size (_session
.get_block_size ());
302 MidiTrack::roll (pframes_t nframes
, framepos_t start_frame
, framepos_t end_frame
, int declick
,
303 bool can_record
, bool rec_monitors_input
, bool& needs_butler
)
305 Glib::RWLock::ReaderLock
lm (_processor_lock
, Glib::TRY_LOCK
);
311 boost::shared_ptr
<MidiDiskstream
> diskstream
= midi_diskstream();
313 automation_snapshot (start_frame
);
315 if (n_outputs().n_total() == 0 && _processors
.empty()) {
324 framepos_t transport_frame
= _session
.transport_frame();
326 if ((nframes
= check_initial_delay (nframes
, transport_frame
)) == 0) {
327 /* need to do this so that the diskstream sets its
328 playback distance to zero, thus causing diskstream::commit
331 return diskstream
->process (transport_frame
, 0, can_record
, rec_monitors_input
, needs_butler
);
336 if ((dret
= diskstream
->process (transport_frame
, nframes
, can_record
, rec_monitors_input
, needs_butler
)) != 0) {
341 /* special condition applies */
343 if (_meter_point
== MeterInput
) {
344 _input
->process_input (_meter
, start_frame
, end_frame
, nframes
);
347 if (diskstream
->record_enabled() && !can_record
&& !_session
.config
.get_auto_input()) {
349 /* not actually recording, but we want to hear the input material anyway,
350 at least potentially (depending on monitoring options)
353 passthru (start_frame
, end_frame
, nframes
, 0);
357 XXX is it true that the earlier test on n_outputs()
358 means that we can avoid checking it again here? i think
359 so, because changing the i/o configuration of an IO
360 requires holding the AudioEngine lock, which we hold
361 while in the process() tree.
365 /* copy the diskstream data to all output buffers */
367 //const size_t limit = n_process_buffers().n_audio();
368 BufferSet
& bufs
= _session
.get_scratch_buffers (n_process_buffers());
369 MidiBuffer
& mbuf (bufs
.get_midi (0));
371 /* we are a MIDI track, so we always start the chain with a single-channel diskstream */
377 diskstream
->get_playback (mbuf
, start_frame
, end_frame
);
379 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
381 write_out_of_band_data (bufs
, start_frame
, end_frame
, nframes
);
383 /* final argument: don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
385 process_output_buffers (bufs
, start_frame
, end_frame
, nframes
,
386 (!_session
.get_record_enabled() || !Config
->get_do_not_record_plugins()), declick
,
387 (!diskstream
->record_enabled() && !_session
.transport_stopped()));
390 _main_outs
->flush_buffers (nframes
, end_frame
- start_frame
- 1);
396 MidiTrack::no_roll (pframes_t nframes
, framepos_t start_frame
, framepos_t end_frame
,
397 bool state_changing
, bool can_record
, bool rec_monitors_input
)
399 int ret
= Track::no_roll (nframes
, start_frame
, end_frame
, state_changing
, can_record
, rec_monitors_input
);
401 if (ret
== 0 && _step_editing
) {
402 push_midi_input_to_step_edit_ringbuffer (nframes
);
409 MidiTrack::realtime_handle_transport_stopped ()
411 Glib::RWLock::ReaderLock
lm (_processor_lock
, Glib::TRY_LOCK
);
416 for (ProcessorList::iterator i
= _processors
.begin(); i
!= _processors
.end(); ++i
) {
417 (*i
)->realtime_handle_transport_stopped ();
422 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes
)
424 PortSet
& ports (_input
->ports());
426 for (PortSet::iterator p
= ports
.begin(DataType::MIDI
); p
!= ports
.end(DataType::MIDI
); ++p
) {
428 Buffer
& b (p
->get_buffer (nframes
));
429 const MidiBuffer
* const mb
= dynamic_cast<MidiBuffer
*>(&b
);
432 for (MidiBuffer::const_iterator e
= mb
->begin(); e
!= mb
->end(); ++e
) {
434 const Evoral::MIDIEvent
<framepos_t
> ev(*e
, false);
436 /* note on, since for step edit, note length is determined
440 if (ev
.is_note_on()) {
441 /* we don't care about the time for this purpose */
442 _step_edit_ring_buffer
.write (0, ev
.type(), ev
.size(), ev
.buffer());
449 MidiTrack::write_out_of_band_data (BufferSet
& bufs
, framepos_t
/*start*/, framepos_t
/*end*/, framecnt_t nframes
)
451 // Append immediate events
452 MidiBuffer
& buf (bufs
.get_midi (0));
453 if (_immediate_events
.read_space()) {
454 DEBUG_TRACE (DEBUG::MidiIO
, string_compose ("%1 has %2 of immediate events to deliver\n",
455 name(), _immediate_events
.read_space()));
457 _immediate_events
.read (buf
, 0, 1, nframes
-1); // all stamps = 0
459 // MIDI thru: send incoming data "through" output
460 if (_midi_thru
&& _session
.transport_speed() != 0.0f
&& _input
->n_ports().n_midi()) {
461 buf
.merge_in_place (_input
->midi(0)->get_midi_buffer(nframes
));
466 MidiTrack::export_stuff (BufferSet
& /*bufs*/, framecnt_t
/*nframes*/, framepos_t
/*end_frame*/)
471 boost::shared_ptr
<Region
>
472 MidiTrack::bounce (InterThreadInfo
& /*itt*/)
475 // vector<MidiSource*> srcs;
476 // return _session.write_one_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
477 return boost::shared_ptr
<Region
> ();
481 boost::shared_ptr
<Region
>
482 MidiTrack::bounce_range (framepos_t
/*start*/, framepos_t
/*end*/, InterThreadInfo
& /*itt*/, bool /*enable_processing*/)
485 //vector<MidiSource*> srcs;
486 //return _session.write_one_track (*this, start, end, false, srcs, itt);
487 return boost::shared_ptr
<Region
> ();
491 MidiTrack::freeze_me (InterThreadInfo
& /*itt*/)
496 MidiTrack::unfreeze ()
498 _freeze_record
.state
= UnFrozen
;
499 FreezeChange (); /* EMIT SIGNAL */
503 MidiTrack::set_note_mode (NoteMode m
)
506 midi_diskstream()->set_note_mode(m
);
510 MidiTrack::midi_panic()
512 DEBUG_TRACE (DEBUG::MidiIO
, string_compose ("%1 delivers panic data\n", name()));
513 for (uint8_t channel
= 0; channel
<= 0xF; channel
++) {
514 uint8_t ev
[3] = { MIDI_CMD_CONTROL
| channel
, MIDI_CTL_SUSTAIN
, 0 };
515 write_immediate_event(3, ev
);
516 ev
[1] = MIDI_CTL_ALL_NOTES_OFF
;
517 write_immediate_event(3, ev
);
518 ev
[1] = MIDI_CTL_RESET_CONTROLLERS
;
519 write_immediate_event(3, ev
);
523 /** \return true on success, false on failure (no buffer space left)
526 MidiTrack::write_immediate_event(size_t size
, const uint8_t* buf
)
528 if (!Evoral::midi_event_is_valid(buf
, size
)) {
529 cerr
<< "WARNING: Ignoring illegal immediate MIDI event" << endl
;
532 const uint32_t type
= EventTypeMap::instance().midi_event_type(buf
[0]);
533 return (_immediate_events
.write(0, type
, size
, buf
) == size
);
537 MidiTrack::MidiControl::set_value(double val
)
541 cerr
<< "MIDIControl value is infinity" << endl
;
542 } else if (isnan(val
)) {
543 cerr
<< "MIDIControl value is NaN" << endl
;
544 } else if (val
< _list
->parameter().min()) {
545 cerr
<< "MIDIControl value is < " << _list
->parameter().min() << endl
;
546 } else if (val
> _list
->parameter().max()) {
547 cerr
<< "MIDIControl value is > " << _list
->parameter().max() << endl
;
556 assert(val
<= _list
->parameter().max());
557 if ( ! automation_playback()) {
559 uint8_t ev
[3] = { _list
->parameter().channel(), int(val
), 0 };
560 switch(_list
->parameter().type()) {
561 case MidiCCAutomation
:
562 ev
[0] += MIDI_CMD_CONTROL
;
563 ev
[1] = _list
->parameter().id();
567 case MidiPgmChangeAutomation
:
569 ev
[0] += MIDI_CMD_PGM_CHANGE
;
573 case MidiChannelPressureAutomation
:
575 ev
[0] += MIDI_CMD_CHANNEL_PRESSURE
;
579 case MidiPitchBenderAutomation
:
580 ev
[0] += MIDI_CMD_BENDER
;
581 ev
[1] = 0x7F & int(val
);
582 ev
[2] = 0x7F & (int(val
) >> 7);
588 _route
->write_immediate_event(size
, ev
);
591 AutomationControl::set_value(val
);
595 MidiTrack::set_step_editing (bool yn
)
597 if (_session
.record_status() != Session::Disabled
) {
601 if (yn
!= _step_editing
) {
603 StepEditStatusChange (yn
);
608 MidiTrack::set_default_channel (uint8_t chn
)
610 _default_channel
= std::min ((unsigned int) chn
, 15U);
614 MidiTrack::set_midi_thru (bool yn
)
619 boost::shared_ptr
<SMFSource
>
620 MidiTrack::write_source (uint32_t)
622 return midi_diskstream()->write_source ();
626 MidiTrack::set_channel_mode (ChannelMode mode
, uint16_t mask
)
628 midi_diskstream()->set_channel_mode (mode
, mask
);
632 MidiTrack::get_channel_mode ()
634 return midi_diskstream()->get_channel_mode ();
638 MidiTrack::get_channel_mask ()
640 return midi_diskstream()->get_channel_mask ();
643 boost::shared_ptr
<MidiPlaylist
>
644 MidiTrack::midi_playlist ()
646 return midi_diskstream()->midi_playlist ();
650 MidiTrack::diskstream_data_recorded (boost::shared_ptr
<MidiBuffer
> buf
, boost::weak_ptr
<MidiSource
> src
)
652 DataRecorded (buf
, src
); /* EMIT SIGNAL */
656 MidiTrack::should_monitor () const
662 MidiTrack::send_silence () const