2 Copyright (C) 2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <pbd/error.h>
21 #include <sigc++/retype.h>
22 #include <sigc++/retype_return.h>
23 #include <sigc++/bind.h>
25 #include <ardour/audio_track.h>
26 #include <ardour/audio_diskstream.h>
27 #include <ardour/session.h>
28 #include <ardour/redirect.h>
29 #include <ardour/audioregion.h>
30 #include <ardour/audiosource.h>
31 #include <ardour/route_group_specialized.h>
32 #include <ardour/insert.h>
33 #include <ardour/audioplaylist.h>
34 #include <ardour/panner.h>
35 #include <ardour/utils.h>
40 using namespace ARDOUR;
43 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
44 : Route (sess, name, 1, -1, -1, -1, flag),
46 _midi_rec_enable_control (*this, _session.midi_port())
48 AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
50 if (_flags & Hidden) {
51 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Hidden);
53 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Recordable);
56 if (mode == Destructive) {
57 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
60 AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags);
63 _freeze_record.state = NoFreeze;
64 _saved_meter_point = _meter_point;
67 set_diskstream (*ds, this);
69 // session.SMPTEOffsetChanged.connect (mem_fun (*this, &AudioTrack::handle_smpte_offset_change));
71 // we do this even though Route already did it in it's init
72 reset_midi_control (_session.midi_port(), _session.get_midi_control());
76 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
77 : Route (sess, "to be renamed", 0, 0, -1, -1),
79 _midi_rec_enable_control (*this, _session.midi_port())
81 _freeze_record.state = NoFreeze;
84 _saved_meter_point = _meter_point;
86 // we do this even though Route already did it in it's init
87 reset_midi_control (_session.midi_port(), _session.get_midi_control());
90 AudioTrack::~AudioTrack ()
99 AudioTrack::handle_smpte_offset_change ()
106 AudioTrack::deprecated_use_diskstream_connections ()
108 if (_diskstream->deprecated_io_node == 0) {
112 const XMLProperty* prop;
113 XMLNode& node (*_diskstream->deprecated_io_node);
115 /* don't do this more than once. */
117 _diskstream->deprecated_io_node = 0;
119 set_input_minimum (-1);
120 set_input_maximum (-1);
121 set_output_minimum (-1);
122 set_output_maximum (-1);
124 if ((prop = node.property ("gain")) != 0) {
125 set_gain (atof (prop->value().c_str()), this);
126 _gain = _desired_gain;
129 if ((prop = node.property ("input-connection")) != 0) {
130 Connection* c = _session.connection_by_name (prop->value());
133 error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
135 if ((c = _session.connection_by_name (_("in 1"))) == 0) {
136 error << _("No input connections available as a replacement")
140 info << string_compose (_("Connection %1 was not available - \"in 1\" used instead"), prop->value())
145 use_input_connection (*c, this);
147 } else if ((prop = node.property ("inputs")) != 0) {
148 if (set_inputs (prop->value())) {
149 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
158 AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
161 _diskstream->unref();
164 _diskstream = &ds.ref();
165 _diskstream->set_io (*this);
166 _diskstream->set_destructive (_mode == Destructive);
168 if (_diskstream->deprecated_io_node) {
170 if (!connecting_legal) {
171 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
173 deprecated_use_diskstream_connections ();
177 _diskstream->set_record_enabled (false, this);
178 _diskstream->monitor_input (false);
180 ic_connection.disconnect();
181 ic_connection = input_changed.connect (mem_fun (*_diskstream, &AudioDiskstream::handle_input_change));
183 diskstream_changed (src); /* EMIT SIGNAL */
189 AudioTrack::use_diskstream (string name)
191 AudioDiskstream *dstream;
193 if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_name (name))) == 0) {
194 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
198 return set_diskstream (*dstream, this);
202 AudioTrack::use_diskstream (id_t id)
204 AudioDiskstream *dstream;
206 if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_id (id))) == 0) {
207 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
211 return set_diskstream (*dstream, this);
215 AudioTrack::record_enabled () const
217 return _diskstream->record_enabled ();
221 AudioTrack::set_record_enable (bool yn, void *src)
223 if (_freeze_record.state == Frozen) {
227 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
228 _mix_group->apply (&AudioTrack::set_record_enable, yn, _mix_group);
232 /* keep track of the meter point as it was before we rec-enabled */
234 if (!_diskstream->record_enabled()) {
235 _saved_meter_point = _meter_point;
238 _diskstream->set_record_enabled (yn, src);
240 if (_diskstream->record_enabled()) {
241 set_meter_point (MeterInput, this);
243 set_meter_point (_saved_meter_point, this);
246 if (_session.get_midi_feedback()) {
247 _midi_rec_enable_control.send_feedback (record_enabled());
253 AudioTrack::set_meter_point (MeterPoint p, void *src)
255 Route::set_meter_point (p, src);
259 AudioTrack::set_state (const XMLNode& node)
261 const XMLProperty *prop;
262 XMLNodeConstIterator iter;
263 XMLNodeList midi_kids;
265 if (Route::set_state (node)) {
269 if ((prop = node.property (X_("mode"))) != 0) {
270 if (prop->value() == X_("normal")) {
272 } else if (prop->value() == X_("destructive")) {
275 warning << string_compose ("unknown audio track mode \"%1\" seen and ignored", prop->value()) << endmsg;
282 midi_kids = node.children ("MIDI");
284 for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
287 XMLNodeConstIterator miter;
290 kids = (*iter)->children ();
292 for (miter = kids.begin(); miter != kids.end(); ++miter) {
296 if (child->name() == "rec_enable") {
298 MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
299 MIDI::byte additional = 0; /* ditto */
300 MIDI::channel_t chn = 0; /* ditto */
302 if (get_midi_node_info (child, ev, chn, additional)) {
303 _midi_rec_enable_control.set_control_type (chn, ev, additional);
305 error << string_compose(_("MIDI rec_enable control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
312 if ((prop = node.property ("diskstream-id")) == 0) {
314 /* some old sessions use the diskstream name rather than the ID */
316 if ((prop = node.property ("diskstream")) == 0) {
317 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
322 if (use_diskstream (prop->value())) {
328 id_t id = strtoull (prop->value().c_str(), 0, 10);
330 if (use_diskstream (id)) {
337 XMLNodeConstIterator niter;
340 nlist = node.children();
341 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
344 if (child->name() == X_("remote_control")) {
345 if ((prop = child->property (X_("id"))) != 0) {
347 sscanf (prop->value().c_str(), "%d", &x);
348 set_remote_control_id (x);
353 pending_state = const_cast<XMLNode*> (&node);
355 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
361 AudioTrack::get_template ()
363 return state (false);
367 AudioTrack::get_state ()
373 AudioTrack::state(bool full_state)
375 XMLNode& root (Route::state(full_state));
376 XMLNode* freeze_node;
379 if (_freeze_record.playlist) {
382 freeze_node = new XMLNode (X_("freeze-info"));
383 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
384 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
385 freeze_node->add_property ("state", buf);
387 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
388 inode = new XMLNode (X_("insert"));
389 snprintf (buf, sizeof (buf), "%" PRIu64, (*i)->id);
390 inode->add_property (X_("id"), buf);
391 inode->add_child_copy ((*i)->state);
393 freeze_node->add_child_nocopy (*inode);
396 root.add_child_nocopy (*freeze_node);
399 /* Alignment: act as a proxy for the diskstream */
401 XMLNode* align_node = new XMLNode (X_("alignment"));
402 switch (_diskstream->alignment_style()) {
403 case ExistingMaterial:
404 snprintf (buf, sizeof (buf), X_("existing"));
407 snprintf (buf, sizeof (buf), X_("capture"));
410 align_node->add_property (X_("style"), buf);
411 root.add_child_nocopy (*align_node);
417 MIDI::byte additional;
418 XMLNode* midi_node = 0;
420 XMLNodeList midikids;
422 midikids = root.children ("MIDI");
423 if (!midikids.empty()) {
424 midi_node = midikids.front();
427 midi_node = root.add_child ("MIDI");
430 if (_midi_rec_enable_control.get_control_info (chn, ev, additional) && midi_node) {
432 child = midi_node->add_child ("rec_enable");
433 set_midi_node_info (child, ev, chn, additional);
436 XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
437 snprintf (buf, sizeof (buf), "%d", _remote_control_id);
438 remote_control_node->add_property (X_("id"), buf);
439 root.add_child_nocopy (*remote_control_node);
443 root.add_property (X_("mode"), X_("normal"));
446 root.add_property (X_("mode"), X_("destructive"));
450 /* we don't return diskstream state because we don't
451 own the diskstream exclusively. control of the diskstream
452 state is ceded to the Session, even if we create the
456 snprintf (buf, sizeof (buf), "%" PRIu64, _diskstream->id());
457 root.add_property ("diskstream-id", buf);
463 AudioTrack::set_state_part_two ()
467 LocaleGuard lg (X_("POSIX"));
469 /* This is called after all session state has been restored but before
470 have been made ports and connections are established.
473 if (pending_state == 0) {
477 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
480 _freeze_record.have_mementos = false;
481 _freeze_record.state = Frozen;
483 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
486 _freeze_record.insert_info.clear ();
488 if ((prop = fnode->property (X_("playlist"))) != 0) {
489 Playlist* pl = _session.playlist_by_name (prop->value());
491 _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl);
493 _freeze_record.playlist = 0;
494 _freeze_record.state = NoFreeze;
499 if ((prop = fnode->property (X_("state"))) != 0) {
500 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
503 XMLNodeConstIterator citer;
504 XMLNodeList clist = fnode->children();
506 for (citer = clist.begin(); citer != clist.end(); ++citer) {
507 if ((*citer)->name() != X_("insert")) {
511 if ((prop = (*citer)->property (X_("id"))) == 0) {
515 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
517 sscanf (prop->value().c_str(), "%" PRIu64, &frii->id);
518 _freeze_record.insert_info.push_back (frii);
522 /* Alignment: act as a proxy for the diskstream */
524 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
526 if ((prop = fnode->property (X_("style"))) != 0) {
527 if (prop->value() == "existing") {
528 _diskstream->set_persistent_align_style (ExistingMaterial);
529 } else if (prop->value() == "capture") {
530 _diskstream->set_persistent_align_style (CaptureTime);
538 AudioTrack::n_process_buffers ()
540 return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
544 AudioTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
546 uint32_t nbufs = n_process_buffers ();
547 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
551 AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
552 bool session_state_changing, bool can_record, bool rec_monitors_input)
554 if (n_outputs() == 0) {
559 silence (nframes, offset);
563 if (session_state_changing) {
565 /* XXX is this safe to do against transport state changes? */
567 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
571 _diskstream->check_record_status (start_frame, nframes, can_record);
575 if (_have_internal_generator) {
576 /* since the instrument has no input streams,
577 there is no reason to send any signal
583 if (_session.get_auto_input()) {
584 if (Config->get_use_sw_monitoring()) {
585 send_silence = false;
590 if (_diskstream->record_enabled()) {
591 if (Config->get_use_sw_monitoring()) {
592 send_silence = false;
602 apply_gain_automation = false;
606 /* if we're sending silence, but we want the meters to show levels for the signal,
610 if (_have_internal_generator) {
611 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
613 if (_meter_point == MeterInput) {
614 just_meter_input (start_frame, end_frame, nframes, offset);
616 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
621 /* we're sending signal, but we may still want to meter the input.
624 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
631 AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
632 bool can_record, bool rec_monitors_input)
637 jack_nframes_t transport_frame;
640 Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
642 // automation snapshot can also be called from the non-rt context
643 // and it uses the redirect list, so we take the lock out here
644 automation_snapshot (start_frame);
648 if (n_outputs() == 0 && _redirects.empty()) {
653 silence (nframes, offset);
657 transport_frame = _session.transport_frame();
659 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
660 /* need to do this so that the diskstream sets its
661 playback distance to zero, thus causing diskstream::commit
664 return _diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
668 apply_gain_automation = false;
670 if ((dret = _diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
672 silence (nframes, offset);
677 /* special condition applies */
679 if (_meter_point == MeterInput) {
680 just_meter_input (start_frame, end_frame, nframes, offset);
683 if (_diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
685 /* not actually recording, but we want to hear the input material anyway,
686 at least potentially (depending on monitoring options)
689 passthru (start_frame, end_frame, nframes, offset, 0, true);
691 } else if ((b = _diskstream->playback_buffer(0)) != 0) {
694 XXX is it true that the earlier test on n_outputs()
695 means that we can avoid checking it again here? i think
696 so, because changing the i/o configuration of an IO
697 requires holding the AudioEngine lock, which we hold
698 while in the process() tree.
702 /* copy the diskstream data to all output buffers */
704 vector<Sample*>& bufs = _session.get_passthru_buffers ();
705 uint32_t limit = n_process_buffers ();
711 for (i = 0, n = 1; i < limit; ++i, ++n) {
712 memcpy (bufs[i], b, sizeof (Sample) * nframes);
713 if (n < _diskstream->n_channels()) {
714 tmpb = _diskstream->playback_buffer(n);
721 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
723 if (!_diskstream->record_enabled() && _session.transport_rolling()) {
724 Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
726 if (am.locked() && gain_automation_playback()) {
727 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
731 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));
734 /* problem with the diskstream; just be quiet for a bit */
735 silence (nframes, offset);
742 AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
743 bool can_record, bool rec_monitors_input)
745 if (n_outputs() == 0 && _redirects.empty()) {
750 silence (nframes, offset);
755 apply_gain_automation = false;
757 silence (nframes, offset);
759 return _diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
763 AudioTrack::toggle_monitor_input ()
765 for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
766 (*i)->request_monitor_input(!(*i)->monitoring_input());
771 AudioTrack::set_name (string str, void *src)
775 if (record_enabled() && _session.actively_recording()) {
776 /* this messes things up if done while recording */
780 if (_diskstream->set_name (str, src)) {
784 /* save state so that the statefile fully reflects any filename changes */
786 if ((ret = IO::set_name (str, src)) == 0) {
787 _session.save_state ("");
793 AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
795 gain_t gain_automation[nframes];
796 gain_t gain_buffer[nframes];
797 float mix_buffer[nframes];
798 RedirectList::iterator i;
799 bool post_fader_work = false;
800 gain_t this_gain = _gain;
801 vector<Sample*>::iterator bi;
804 Glib::RWLock::ReaderLock rlock (redirect_lock);
807 AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(_diskstream->playlist());
810 if (apl->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
815 bi = buffers.begin();
818 for (; bi != buffers.end(); ++bi, ++n) {
819 if (n < _diskstream->n_channels()) {
820 if (apl->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
826 /* duplicate last across remaining buffers */
827 memcpy ((*bi), b, sizeof (Sample) * nframes);
832 /* note: only run inserts during export. other layers in the machinery
833 will already have checked that there are no external port inserts.
836 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
839 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
840 switch (insert->placement()) {
842 insert->run (buffers, nbufs, nframes, 0);
845 post_fader_work = true;
851 if (_gain_automation_curve.automation_state() == Play) {
853 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
855 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
857 for (jack_nframes_t n = 0; n < nframes; ++n) {
858 b[n] *= gain_automation[n];
864 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
866 for (jack_nframes_t n = 0; n < nframes; ++n) {
872 if (post_fader_work) {
874 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
875 PluginInsert *insert;
877 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
878 switch ((*i)->placement()) {
882 insert->run (buffers, nbufs, nframes, 0);
893 AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
895 Route::set_latency_delay (longest_session_latency);
896 _diskstream->set_roll_delay (_roll_delay);
900 AudioTrack::update_total_latency ()
904 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
905 if ((*i)->active ()) {
906 _own_latency += (*i)->latency ();
910 set_port_latency (_own_latency);
916 AudioTrack::bounce (InterThreadInfo& itt)
918 vector<AudioSource*> srcs;
919 _session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
924 AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
926 vector<AudioSource*> srcs;
927 _session.write_one_audio_track (*this, start, end, false, srcs, itt);
931 AudioTrack::freeze (InterThreadInfo& itt)
934 vector<AudioSource*> srcs;
935 string new_playlist_name;
936 Playlist* new_playlist;
941 if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(_diskstream->playlist())) == 0) {
947 while (n < (UINT_MAX-1)) {
951 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
953 if (_session.playlist_by_name (candidate) == 0) {
954 new_playlist_name = candidate;
962 if (n == (UINT_MAX-1)) {
963 error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
964 " to create another one"), _freeze_record.playlist->name())
969 if (_session.write_one_audio_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
973 _freeze_record.insert_info.clear ();
974 _freeze_record.have_mementos = true;
977 Glib::RWLock::ReaderLock lm (redirect_lock);
979 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
981 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
983 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
985 frii->insert = insert;
986 frii->id = insert->id();
987 frii->memento = (*r)->get_memento();
989 _freeze_record.insert_info.push_back (frii);
991 /* now deactivate the insert */
993 insert->set_active (false, this);
998 new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
999 region_name = new_playlist_name;
1001 /* create a new region from all filesources, keep it private */
1003 region = new AudioRegion (srcs, 0, srcs[0]->length(),
1005 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
1008 new_playlist->set_orig_diskstream_id (_diskstream->id());
1009 new_playlist->add_region (*region, 0);
1010 new_playlist->set_frozen (true);
1011 region->set_locked (true);
1013 _diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
1014 _diskstream->set_record_enabled (false, this);
1016 _freeze_record.state = Frozen;
1017 FreezeChange(); /* EMIT SIGNAL */
1021 AudioTrack::unfreeze ()
1023 if (_freeze_record.playlist) {
1024 _diskstream->use_playlist (_freeze_record.playlist);
1026 if (_freeze_record.have_mementos) {
1028 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
1034 Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
1035 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1036 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
1037 if ((*ii)->id == (*i)->id()) {
1038 (*i)->set_state (((*ii)->state));
1045 _freeze_record.playlist = 0;
1048 _freeze_record.state = UnFrozen;
1049 FreezeChange (); /* EMIT SIGNAL */
1052 AudioTrack::FreezeRecord::~FreezeRecord ()
1054 for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
1059 AudioTrack::FreezeState
1060 AudioTrack::freeze_state() const
1062 return _freeze_record.state;
1067 AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
1069 MIDI::channel_t chn;
1073 Route::reset_midi_control (port, on);
1075 _midi_rec_enable_control.get_control_info (chn, ev, extra);
1079 _midi_rec_enable_control.midi_rebind (port, chn);
1083 AudioTrack::send_all_midi_feedback ()
1085 if (_session.get_midi_feedback()) {
1087 Route::send_all_midi_feedback();
1089 _midi_rec_enable_control.send_feedback (record_enabled());
1094 AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s, MIDI::Port* port)
1095 : MIDI::Controllable (port, 0), track (s), setting(false)
1097 last_written = false; /* XXX need a good out of bound value */
1101 AudioTrack::MIDIRecEnableControl::set_value (float val)
1103 bool bval = ((val >= 0.5f) ? true: false);
1106 track.set_record_enable (bval, this);
1111 AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
1114 if (!setting && get_midi_feedback()) {
1115 MIDI::byte val = (MIDI::byte) (value ? 127: 0);
1116 MIDI::channel_t ch = 0;
1117 MIDI::eventType ev = MIDI::none;
1118 MIDI::byte additional = 0;
1119 MIDI::EventTwoBytes data;
1121 if (get_control_info (ch, ev, additional)) {
1122 data.controller_number = additional;
1125 track._session.send_midi_message (get_port(), ev, ch, data);
1132 AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
1134 if (get_midi_feedback()) {
1136 MIDI::channel_t ch = 0;
1137 MIDI::eventType ev = MIDI::none;
1138 MIDI::byte additional = 0;
1140 if (get_control_info (ch, ev, additional)) {
1141 if (val != last_written || force) {
1143 *buf++ = additional; /* controller number */
1144 *buf++ = (MIDI::byte) (val ? 127: 0);
1155 AudioTrack::set_mode (TrackMode m)
1160 _diskstream->set_destructive (m == Destructive);