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 <ardour/midi_track.h>
25 #include <ardour/midi_diskstream.h>
26 #include <ardour/session.h>
27 #include <ardour/redirect.h>
28 #include <ardour/midi_region.h>
29 #include <ardour/midi_source.h>
30 #include <ardour/route_group_specialized.h>
31 #include <ardour/insert.h>
32 #include <ardour/midi_playlist.h>
33 #include <ardour/panner.h>
34 #include <ardour/utils.h>
39 using namespace ARDOUR;
42 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
43 : Track (sess, name, flag, mode, Buffer::MIDI)
45 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
47 if (_flags & Hidden) {
48 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
50 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
53 if (mode == Destructive) {
54 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Destructive);
57 MidiDiskstream* ds = new MidiDiskstream (_session, name, dflags);
60 _freeze_record.state = NoFreeze;
61 _saved_meter_point = _meter_point;
64 set_diskstream (*ds, this);
67 MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
70 _freeze_record.state = NoFreeze;
73 _saved_meter_point = _meter_point;
76 MidiTrack::~MidiTrack ()
85 MidiTrack::handle_smpte_offset_change ()
93 MidiTrack::set_diskstream (MidiDiskstream& ds, void *src)
99 _diskstream = &ds.ref();
100 _diskstream->set_io (*this);
101 _diskstream->set_destructive (_mode == Destructive);
103 _diskstream->set_record_enabled (false, this);
104 //_diskstream->monitor_input (false);
106 ic_connection.disconnect();
107 ic_connection = input_changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
109 DiskstreamChanged (src); /* EMIT SIGNAL */
115 MidiTrack::use_diskstream (string name)
117 MidiDiskstream *dstream;
119 if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_name (name))) == 0) {
120 error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
124 return set_diskstream (*dstream, this);
128 MidiTrack::use_diskstream (const PBD::ID& id)
130 MidiDiskstream *dstream;
132 if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_id (id))) == 0) {
133 error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), id) << endmsg;
137 return set_diskstream (*dstream, this);
141 MidiTrack::record_enabled () const
143 return _diskstream->record_enabled ();
147 MidiTrack::set_record_enable (bool yn, void *src)
149 if (_freeze_record.state == Frozen) {
153 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
154 _mix_group->apply (&MidiTrack::set_record_enable, yn, _mix_group);
158 /* keep track of the meter point as it was before we rec-enabled */
160 if (!diskstream->record_enabled()) {
161 _saved_meter_point = _meter_point;
164 diskstream->set_record_enabled (yn, src);
166 if (diskstream->record_enabled()) {
167 set_meter_point (MeterInput, this);
169 set_meter_point (_saved_meter_point, this);
172 if (_session.get_midi_feedback()) {
173 _midi_rec_enable_control.send_feedback (record_enabled());
179 MidiTrack::midi_diskstream() const
181 return *dynamic_cast<MidiDiskstream*>(_diskstream);
185 MidiTrack::set_state (const XMLNode& node)
187 const XMLProperty *prop;
188 XMLNodeConstIterator iter;
190 if (Route::set_state (node)) {
194 if ((prop = node.property (X_("mode"))) != 0) {
195 if (prop->value() == X_("normal")) {
197 } else if (prop->value() == X_("destructive")) {
200 warning << string_compose ("unknown midi track mode \"%1\" seen and ignored", prop->value()) << endmsg;
207 if ((prop = node.property ("diskstream-id")) == 0) {
209 /* some old sessions use the diskstream name rather than the ID */
211 if ((prop = node.property ("diskstream")) == 0) {
212 fatal << _("programming error: MidiTrack given state without diskstream!") << endmsg;
217 if (use_diskstream (prop->value())) {
223 PBD::ID id (prop->value());
225 if (use_diskstream (id)) {
232 XMLNodeConstIterator niter;
235 nlist = node.children();
236 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
239 if (child->name() == X_("remote_control")) {
240 if ((prop = child->property (X_("id"))) != 0) {
242 sscanf (prop->value().c_str(), "%d", &x);
243 set_remote_control_id (x);
248 pending_state = const_cast<XMLNode*> (&node);
250 _session.StateReady.connect (mem_fun (*this, &MidiTrack::set_state_part_two));
256 MidiTrack::state(bool full_state)
258 XMLNode& root (Route::state(full_state));
259 XMLNode* freeze_node;
262 if (_freeze_record.playlist) {
265 freeze_node = new XMLNode (X_("freeze-info"));
266 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
267 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
268 freeze_node->add_property ("state", buf);
270 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
271 inode = new XMLNode (X_("insert"));
272 (*i)->id.print (buf);
273 inode->add_property (X_("id"), buf);
274 inode->add_child_copy ((*i)->state);
276 freeze_node->add_child_nocopy (*inode);
279 root.add_child_nocopy (*freeze_node);
282 /* Alignment: act as a proxy for the diskstream */
284 XMLNode* align_node = new XMLNode (X_("alignment"));
285 switch (_diskstream->alignment_style()) {
286 case ExistingMaterial:
287 snprintf (buf, sizeof (buf), X_("existing"));
290 snprintf (buf, sizeof (buf), X_("capture"));
293 align_node->add_property (X_("style"), buf);
294 root.add_child_nocopy (*align_node);
296 XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
297 snprintf (buf, sizeof (buf), "%d", _remote_control_id);
298 remote_control_node->add_property (X_("id"), buf);
299 root.add_child_nocopy (*remote_control_node);
303 root.add_property (X_("mode"), X_("normal"));
306 root.add_property (X_("mode"), X_("destructive"));
310 /* we don't return diskstream state because we don't
311 own the diskstream exclusively. control of the diskstream
312 state is ceded to the Session, even if we create the
316 _diskstream->id().print (buf);
317 root.add_property ("diskstream-id", buf);
323 MidiTrack::set_state_part_two ()
327 LocaleGuard lg (X_("POSIX"));
329 /* This is called after all session state has been restored but before
330 have been made ports and connections are established.
333 if (pending_state == 0) {
337 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
340 _freeze_record.have_mementos = false;
341 _freeze_record.state = Frozen;
343 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
346 _freeze_record.insert_info.clear ();
348 if ((prop = fnode->property (X_("playlist"))) != 0) {
349 Playlist* pl = _session.playlist_by_name (prop->value());
351 _freeze_record.playlist = dynamic_cast<MidiPlaylist*> (pl);
353 _freeze_record.playlist = 0;
354 _freeze_record.state = NoFreeze;
359 if ((prop = fnode->property (X_("state"))) != 0) {
360 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
363 XMLNodeConstIterator citer;
364 XMLNodeList clist = fnode->children();
366 for (citer = clist.begin(); citer != clist.end(); ++citer) {
367 if ((*citer)->name() != X_("insert")) {
371 if ((prop = (*citer)->property (X_("id"))) == 0) {
375 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
377 frii->id = prop->value ();
378 _freeze_record.insert_info.push_back (frii);
382 /* Alignment: act as a proxy for the diskstream */
384 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
386 if ((prop = fnode->property (X_("style"))) != 0) {
387 if (prop->value() == "existing") {
388 _diskstream->set_persistent_align_style (ExistingMaterial);
389 } else if (prop->value() == "capture") {
390 _diskstream->set_persistent_align_style (CaptureTime);
398 MidiTrack::n_process_buffers ()
400 return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
404 MidiTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
406 uint32_t nbufs = n_process_buffers ();
407 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
411 MidiTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
412 bool session_state_changing, bool can_record, bool rec_monitors_input)
414 if (n_outputs() == 0) {
419 silence (nframes, offset);
423 if (session_state_changing) {
425 /* XXX is this safe to do against transport state changes? */
427 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
431 midi_diskstream().check_record_status (start_frame, nframes, can_record);
435 if (_have_internal_generator) {
436 /* since the instrument has no input streams,
437 there is no reason to send any signal
443 if (_session.get_auto_input()) {
444 if (Config->get_use_sw_monitoring()) {
445 send_silence = false;
450 if (_diskstream->record_enabled()) {
451 if (Config->get_use_sw_monitoring()) {
452 send_silence = false;
462 apply_gain_automation = false;
466 /* if we're sending silence, but we want the meters to show levels for the signal,
470 if (_have_internal_generator) {
471 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
473 if (_meter_point == MeterInput) {
474 just_meter_input (start_frame, end_frame, nframes, offset);
476 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
481 /* we're sending signal, but we may still want to meter the input.
484 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
491 MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
492 bool can_record, bool rec_monitors_input)
498 jack_nframes_t transport_frame;
501 Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
503 // automation snapshot can also be called from the non-rt context
504 // and it uses the redirect list, so we take the lock out here
505 automation_snapshot (start_frame);
509 if (n_outputs() == 0 && _redirects.empty()) {
514 silence (nframes, offset);
518 transport_frame = _session.transport_frame();
520 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
521 /* need to do this so that the diskstream sets its
522 playback distance to zero, thus causing diskstream::commit
525 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
529 apply_gain_automation = false;
531 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
533 silence (nframes, offset);
538 /* special condition applies */
540 if (_meter_point == MeterInput) {
541 just_meter_input (start_frame, end_frame, nframes, offset);
544 if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
546 /* not actually recording, but we want to hear the input material anyway,
547 at least potentially (depending on monitoring options)
550 passthru (start_frame, end_frame, nframes, offset, 0, true);
552 } else if ((b = diskstream->playback_buffer(0)) != 0) {
555 XXX is it true that the earlier test on n_outputs()
556 means that we can avoid checking it again here? i think
557 so, because changing the i/o configuration of an IO
558 requires holding the AudioEngine lock, which we hold
559 while in the process() tree.
563 /* copy the diskstream data to all output buffers */
565 vector<Sample*>& bufs = _session.get_passthru_buffers ();
566 uint32_t limit = n_process_buffers ();
572 for (i = 0, n = 1; i < limit; ++i, ++n) {
573 memcpy (bufs[i], b, sizeof (Sample) * nframes);
574 if (n < diskstream->n_channels()) {
575 tmpb = diskstream->playback_buffer(n);
582 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
584 if (!diskstream->record_enabled() && _session.transport_rolling()) {
585 Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
587 if (am.locked() && gain_automation_playback()) {
588 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
592 process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
595 /* problem with the diskstream; just be quiet for a bit */
596 silence (nframes, offset);
603 MidiTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
604 bool can_record, bool rec_monitors_input)
606 if (n_outputs() == 0 && _redirects.empty()) {
611 silence (nframes, offset);
616 apply_gain_automation = false;
618 silence (nframes, offset);
620 return midi_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
624 MidiTrack::set_name (string str, void *src)
628 if (record_enabled() && _session.actively_recording()) {
629 /* this messes things up if done while recording */
633 if (_diskstream->set_name (str, src)) {
637 /* save state so that the statefile fully reflects any filename changes */
639 if ((ret = IO::set_name (str, src)) == 0) {
640 _session.save_state ("");
646 MidiTrack::export_stuff (vector<unsigned char*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
649 gain_t gain_automation[nframes];
650 gain_t gain_buffer[nframes];
651 float mix_buffer[nframes];
652 RedirectList::iterator i;
653 bool post_fader_work = false;
654 gain_t this_gain = _gain;
655 vector<Sample*>::iterator bi;
658 Glib::RWLock::ReaderLock rlock (redirect_lock);
660 if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
665 bi = buffers.begin();
668 for (; bi != buffers.end(); ++bi, ++n) {
669 if (n < diskstream->n_channels()) {
670 if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
676 /* duplicate last across remaining buffers */
677 memcpy ((*bi), b, sizeof (Sample) * nframes);
682 /* note: only run inserts during export. other layers in the machinery
683 will already have checked that there are no external port inserts.
686 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
689 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
690 switch (insert->placement()) {
692 insert->run (buffers, nbufs, nframes, 0);
695 post_fader_work = true;
701 if (_gain_automation_curve.automation_state() == Play) {
703 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
705 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
707 for (jack_nframes_t n = 0; n < nframes; ++n) {
708 b[n] *= gain_automation[n];
714 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
716 for (jack_nframes_t n = 0; n < nframes; ++n) {
722 if (post_fader_work) {
724 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
725 PluginInsert *insert;
727 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
728 switch ((*i)->placement()) {
732 insert->run (buffers, nbufs, nframes, 0);
743 MidiTrack::set_latency_delay (jack_nframes_t longest_session_latency)
745 Route::set_latency_delay (longest_session_latency);
746 _diskstream->set_roll_delay (_roll_delay);
750 MidiTrack::bounce (InterThreadInfo& itt)
752 //vector<MidiSource*> srcs;
753 //_session.write_one_midi_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
758 MidiTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
760 //vector<MidiSource*> srcs;
761 //_session.write_one_midi_track (*this, start, end, false, srcs, itt);
765 MidiTrack::freeze (InterThreadInfo& itt)
769 vector<MidiSource*> srcs;
770 string new_playlist_name;
771 Playlist* new_playlist;
776 if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
782 while (n < (UINT_MAX-1)) {
786 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
788 if (_session.playlist_by_name (candidate) == 0) {
789 new_playlist_name = candidate;
797 if (n == (UINT_MAX-1)) {
798 PBD::error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
799 " to create another one"), _freeze_record.playlist->name())
804 if (_session.write_one_midi_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
808 _freeze_record.insert_info.clear ();
809 _freeze_record.have_mementos = true;
812 Glib::RWLock::ReaderLock lm (redirect_lock);
814 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
816 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
818 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
820 frii->insert = insert;
821 frii->id = insert->id();
822 frii->memento = (*r)->get_memento();
824 _freeze_record.insert_info.push_back (frii);
826 /* now deactivate the insert */
828 insert->set_active (false, this);
833 new_playlist = new MidiPlaylist (_session, new_playlist_name, false);
834 region_name = new_playlist_name;
836 /* create a new region from all filesources, keep it private */
838 region = new AudioRegion (srcs, 0, srcs[0]->length(),
840 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
843 new_playlist->set_orig_diskstream_id (diskstream->id());
844 new_playlist->add_region (*region, 0);
845 new_playlist->set_frozen (true);
846 region->set_locked (true);
848 diskstream->use_playlist (dynamic_cast<MidiPlaylist*>(new_playlist));
849 diskstream->set_record_enabled (false, this);
851 _freeze_record.state = Frozen;
852 FreezeChange(); /* EMIT SIGNAL */
857 MidiTrack::unfreeze ()
860 if (_freeze_record.playlist) {
861 diskstream->use_playlist (_freeze_record.playlist);
863 if (_freeze_record.have_mementos) {
865 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
871 Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
872 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
873 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
874 if ((*ii)->id == (*i)->id()) {
875 (*i)->set_state (((*ii)->state));
882 _freeze_record.playlist = 0;
885 _freeze_record.state = UnFrozen;
886 FreezeChange (); /* EMIT SIGNAL */
890 MidiTrack::set_mode (TrackMode m)
895 _diskstream->set_destructive (m == Destructive);