2 Copyright (C) 2006 Paul Davis
3 By Dave Robillard, 2006
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.
19 #include <pbd/error.h>
20 #include <sigc++/retype.h>
21 #include <sigc++/retype_return.h>
22 #include <sigc++/bind.h>
24 #include <pbd/enumwriter.h>
26 #include <ardour/midi_track.h>
27 #include <ardour/midi_diskstream.h>
28 #include <ardour/session.h>
29 #include <ardour/redirect.h>
30 #include <ardour/midi_region.h>
31 #include <ardour/midi_source.h>
32 #include <ardour/route_group_specialized.h>
33 #include <ardour/insert.h>
34 #include <ardour/midi_playlist.h>
35 #include <ardour/panner.h>
36 #include <ardour/utils.h>
37 #include <ardour/buffer_set.h>
38 #include <ardour/meter.h>
43 using namespace ARDOUR;
46 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
47 : Track (sess, name, flag, mode, DataType::MIDI)
49 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
51 if (_flags & Hidden) {
52 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
54 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
57 assert(mode != Destructive);
59 boost::shared_ptr<MidiDiskstream> ds (new MidiDiskstream (_session, name, dflags));
60 _session.add_diskstream (ds);
62 set_diskstream (boost::dynamic_pointer_cast<MidiDiskstream> (ds));
65 _freeze_record.state = NoFreeze;
66 _saved_meter_point = _meter_point;
69 set_input_minimum(ChanCount(DataType::MIDI, 1));
70 set_input_maximum(ChanCount(DataType::MIDI, 1));
71 set_output_minimum(ChanCount(DataType::MIDI, 1));
72 set_output_maximum(ChanCount(DataType::MIDI, 1));
75 MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
78 _set_state(node, false);
80 set_input_minimum(ChanCount(DataType::MIDI, 1));
81 set_input_maximum(ChanCount(DataType::MIDI, 1));
82 set_output_minimum(ChanCount(DataType::MIDI, 1));
83 set_output_maximum(ChanCount(DataType::MIDI, 1));
86 MidiTrack::~MidiTrack ()
92 MidiTrack::set_diskstream (boost::shared_ptr<MidiDiskstream> ds)
95 _diskstream->set_io (*this);
96 _diskstream->set_destructive (_mode == Destructive);
98 _diskstream->set_record_enabled (false);
99 //_diskstream->monitor_input (false);
101 ic_connection.disconnect();
102 ic_connection = input_changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
104 DiskstreamChanged (); /* EMIT SIGNAL */
110 MidiTrack::use_diskstream (string name)
112 boost::shared_ptr<MidiDiskstream> dstream;
114 if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream>(_session.diskstream_by_name (name))) == 0) {
115 error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
119 return set_diskstream (dstream);
123 MidiTrack::use_diskstream (const PBD::ID& id)
125 boost::shared_ptr<MidiDiskstream> dstream;
127 if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream> (_session.diskstream_by_id (id))) == 0) {
128 error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), id) << endmsg;
132 return set_diskstream (dstream);
135 boost::shared_ptr<MidiDiskstream>
136 MidiTrack::midi_diskstream() const
138 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
142 MidiTrack::set_state (const XMLNode& node)
144 return _set_state (node, true);
148 MidiTrack::_set_state (const XMLNode& node, bool call_base)
150 const XMLProperty *prop;
151 XMLNodeConstIterator iter;
153 if (Route::_set_state (node, call_base)) {
157 if ((prop = node.property (X_("mode"))) != 0) {
158 _mode = TrackMode (string_2_enum (prop->value(), _mode));
163 if ((prop = node.property ("diskstream-id")) == 0) {
165 /* some old sessions use the diskstream name rather than the ID */
167 if ((prop = node.property ("diskstream")) == 0) {
168 fatal << _("programming error: MidiTrack given state without diskstream!") << endmsg;
173 if (use_diskstream (prop->value())) {
179 PBD::ID id (prop->value());
181 if (use_diskstream (id)) {
188 XMLNodeConstIterator niter;
191 nlist = node.children();
192 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
195 if (child->name() == X_("recenable")) {
196 _rec_enable_control.set_state (*child);
197 _session.add_controllable (&_rec_enable_control);
201 pending_state = const_cast<XMLNode*> (&node);
203 _session.StateReady.connect (mem_fun (*this, &MidiTrack::set_state_part_two));
209 MidiTrack::state(bool full_state)
211 XMLNode& root (Route::state(full_state));
212 XMLNode* freeze_node;
215 if (_freeze_record.playlist) {
218 freeze_node = new XMLNode (X_("freeze-info"));
219 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
220 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
222 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
223 inode = new XMLNode (X_("insert"));
224 (*i)->id.print (buf, sizeof(buf));
225 inode->add_property (X_("id"), buf);
226 inode->add_child_copy ((*i)->state);
228 freeze_node->add_child_nocopy (*inode);
231 root.add_child_nocopy (*freeze_node);
234 /* Alignment: act as a proxy for the diskstream */
236 XMLNode* align_node = new XMLNode (X_("alignment"));
237 AlignStyle as = _diskstream->alignment_style ();
238 align_node->add_property (X_("style"), enum_2_string (as));
239 root.add_child_nocopy (*align_node);
241 root.add_property (X_("mode"), enum_2_string (_mode));
243 /* we don't return diskstream state because we don't
244 own the diskstream exclusively. control of the diskstream
245 state is ceded to the Session, even if we create the
249 _diskstream->id().print (buf, sizeof(buf));
250 root.add_property ("diskstream-id", buf);
252 root.add_child_nocopy (_rec_enable_control.get_state());
258 MidiTrack::set_state_part_two ()
262 LocaleGuard lg (X_("POSIX"));
264 /* This is called after all session state has been restored but before
265 have been made ports and connections are established.
268 if (pending_state == 0) {
272 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
275 _freeze_record.have_mementos = false;
276 _freeze_record.state = Frozen;
278 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
281 _freeze_record.insert_info.clear ();
283 if ((prop = fnode->property (X_("playlist"))) != 0) {
284 boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value());
286 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
288 _freeze_record.playlist.reset();
289 _freeze_record.state = NoFreeze;
294 if ((prop = fnode->property (X_("state"))) != 0) {
295 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
298 XMLNodeConstIterator citer;
299 XMLNodeList clist = fnode->children();
301 for (citer = clist.begin(); citer != clist.end(); ++citer) {
302 if ((*citer)->name() != X_("insert")) {
306 if ((prop = (*citer)->property (X_("id"))) == 0) {
310 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()),
311 boost::shared_ptr<Insert>());
312 frii->id = prop->value ();
313 _freeze_record.insert_info.push_back (frii);
317 /* Alignment: act as a proxy for the diskstream */
319 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
321 if ((prop = fnode->property (X_("style"))) != 0) {
323 /* fix for older sessions from before EnumWriter */
327 if (prop->value() == "capture") {
328 pstr = "CaptureTime";
329 } else if (prop->value() == "existing") {
330 pstr = "ExistingMaterial";
332 pstr = prop->value();
335 AlignStyle as = AlignStyle (string_2_enum (pstr, as));
336 _diskstream->set_persistent_align_style (as);
343 MidiTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
344 bool session_state_changing, bool can_record, bool rec_monitors_input)
346 if (n_outputs().n_midi() == 0) {
352 silence (nframes, offset);
356 if (session_state_changing) {
358 /* XXX is this safe to do against transport state changes? */
360 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
364 midi_diskstream()->check_record_status (start_frame, nframes, can_record);
368 if (_have_internal_generator) {
369 /* since the instrument has no input streams,
370 there is no reason to send any signal
376 if (Config->get_auto_input()) {
377 if (Config->get_monitoring_model() == SoftwareMonitoring) {
378 send_silence = false;
383 if (_diskstream->record_enabled()) {
384 if (Config->get_monitoring_model() == SoftwareMonitoring) {
385 send_silence = false;
395 apply_gain_automation = false;
399 /* if we're sending silence, but we want the meters to show levels for the signal,
403 if (_have_internal_generator) {
404 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
406 if (_meter_point == MeterInput) {
407 just_meter_input (start_frame, end_frame, nframes, offset);
409 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
414 /* we're sending signal, but we may still want to meter the input.
417 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
424 MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick,
425 bool can_record, bool rec_monitors_input)
428 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
430 if (n_outputs().n_total() == 0 && _inserts.empty()) {
435 silence (nframes, offset);
439 nframes_t transport_frame = _session.transport_frame();
441 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
442 /* need to do this so that the diskstream sets its
443 playback distance to zero, thus causing diskstream::commit
446 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
451 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
453 silence (nframes, offset);
458 /* special condition applies */
460 if (_meter_point == MeterInput) {
461 just_meter_input (start_frame, end_frame, nframes, offset);
464 if (diskstream->record_enabled() && !can_record && !Config->get_auto_input()) {
466 /* not actually recording, but we want to hear the input material anyway,
467 at least potentially (depending on monitoring options)
470 passthru (start_frame, end_frame, nframes, offset, 0, true);
474 XXX is it true that the earlier test on n_outputs()
475 means that we can avoid checking it again here? i think
476 so, because changing the i/o configuration of an IO
477 requires holding the AudioEngine lock, which we hold
478 while in the process() tree.
482 /* copy the diskstream data to all output buffers */
484 //const size_t limit = n_process_buffers().n_audio();
485 BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
487 diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame);
489 process_output_buffers (bufs, start_frame, end_frame, nframes, offset,
490 (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
498 MidiTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
499 bool can_record, bool rec_monitors_input)
501 if (n_outputs().n_midi() == 0 && _inserts.empty()) {
506 silence (nframes, offset);
511 apply_gain_automation = false;
513 silence (nframes, offset);
515 return midi_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
519 MidiTrack::process_output_buffers (BufferSet& bufs,
520 nframes_t start_frame, nframes_t end_frame,
521 nframes_t nframes, nframes_t offset, bool with_inserts, int declick,
524 /* There's no such thing as a MIDI bus for the time being.
525 * We'll do all the MIDI route work here for now, but the long-term goal is to have
526 * Route::process_output_buffers handle everything */
528 if (meter && (_meter_point == MeterInput || _meter_point == MeterPreFader)) {
529 _meter->run(bufs, start_frame, end_frame, nframes, offset);
534 Glib::RWLock::ReaderLock rm (insert_lock, Glib::TRY_LOCK);
536 for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
537 (*i)->run (bufs, start_frame, end_frame, nframes, offset);
542 if (meter && (_meter_point == MeterPostFader)) {
543 _meter->run(bufs, start_frame, end_frame, nframes, offset);
548 IO::silence(nframes, offset);
550 deliver_output(bufs, start_frame, end_frame, nframes, offset);
555 MidiTrack::export_stuff (BufferSet& bufs, nframes_t nframes, nframes_t end_frame)
561 MidiTrack::set_latency_delay (nframes_t longest_session_latency)
563 Route::set_latency_delay (longest_session_latency);
564 _diskstream->set_roll_delay (_roll_delay);
568 MidiTrack::bounce (InterThreadInfo& itt)
571 //vector<MidiSource*> srcs;
572 //_session.write_one_midi_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
577 MidiTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt)
580 //vector<MidiSource*> srcs;
581 //_session.write_one_midi_track (*this, start, end, false, srcs, itt);
585 MidiTrack::freeze (InterThreadInfo& itt)
590 MidiTrack::unfreeze ()
592 _freeze_record.state = UnFrozen;
593 FreezeChange (); /* EMIT SIGNAL */
597 MidiTrack::set_mode (TrackMode m)
603 if (_diskstream->set_destructive (m == Destructive)) {
609 TrackModeChanged (); /* EMIT SIGNAL */