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 ()
98 AudioTrack::deprecated_use_diskstream_connections ()
100 if (diskstream->deprecated_io_node == 0) {
104 const XMLProperty* prop;
105 XMLNode& node (*diskstream->deprecated_io_node);
107 /* don't do this more than once. */
109 diskstream->deprecated_io_node = 0;
111 set_input_minimum (-1);
112 set_input_maximum (-1);
113 set_output_minimum (-1);
114 set_output_maximum (-1);
116 if ((prop = node.property ("gain")) != 0) {
117 set_gain (atof (prop->value().c_str()), this);
118 _gain = _desired_gain;
121 if ((prop = node.property ("input-connection")) != 0) {
122 Connection* c = _session.connection_by_name (prop->value());
125 error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
127 if ((c = _session.connection_by_name (_("in 1"))) == 0) {
128 error << _("No input connections available as a replacement")
132 info << string_compose (_("Connection %1 was not available - \"in 1\" used instead"), prop->value())
137 use_input_connection (*c, this);
139 } else if ((prop = node.property ("inputs")) != 0) {
140 if (set_inputs (prop->value())) {
141 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
150 AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
156 diskstream = &ds.ref();
157 diskstream->set_io (*this);
158 diskstream->set_destructive (_mode == Destructive);
160 if (diskstream->deprecated_io_node) {
162 if (!connecting_legal) {
163 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
165 deprecated_use_diskstream_connections ();
169 diskstream->set_record_enabled (false, this);
170 diskstream->monitor_input (false);
172 ic_connection.disconnect();
173 ic_connection = input_changed.connect (mem_fun (*diskstream, &AudioDiskstream::handle_input_change));
175 diskstream_changed (src); /* EMIT SIGNAL */
181 AudioTrack::use_diskstream (string name)
183 AudioDiskstream *dstream;
185 if ((dstream = _session.diskstream_by_name (name)) == 0) {
186 error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg;
190 return set_diskstream (*dstream, this);
194 AudioTrack::use_diskstream (id_t id)
196 AudioDiskstream *dstream;
198 if ((dstream = _session.diskstream_by_id (id)) == 0) {
199 error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg;
203 return set_diskstream (*dstream, this);
207 AudioTrack::record_enabled () const
209 return diskstream->record_enabled ();
213 AudioTrack::set_record_enable (bool yn, void *src)
215 if (_freeze_record.state == Frozen) {
219 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
220 _mix_group->apply (&AudioTrack::set_record_enable, yn, _mix_group);
224 /* keep track of the meter point as it was before we rec-enabled */
226 if (!diskstream->record_enabled()) {
227 _saved_meter_point = _meter_point;
230 diskstream->set_record_enabled (yn, src);
232 if (diskstream->record_enabled()) {
233 set_meter_point (MeterInput, this);
235 set_meter_point (_saved_meter_point, this);
238 if (_session.get_midi_feedback()) {
239 _midi_rec_enable_control.send_feedback (record_enabled());
245 AudioTrack::set_meter_point (MeterPoint p, void *src)
247 Route::set_meter_point (p, src);
251 AudioTrack::set_state (const XMLNode& node)
253 const XMLProperty *prop;
254 XMLNodeConstIterator iter;
255 XMLNodeList midi_kids;
257 if (Route::set_state (node)) {
261 if ((prop = node.property (X_("mode"))) != 0) {
262 if (prop->value() == X_("normal")) {
264 } else if (prop->value() == X_("destructive")) {
267 warning << string_compose ("unknown audio track mode \"%1\" seen and ignored", prop->value()) << endmsg;
274 midi_kids = node.children ("MIDI");
276 for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
279 XMLNodeConstIterator miter;
282 kids = (*iter)->children ();
284 for (miter = kids.begin(); miter != kids.end(); ++miter) {
288 if (child->name() == "rec_enable") {
290 MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
291 MIDI::byte additional = 0; /* ditto */
292 MIDI::channel_t chn = 0; /* ditto */
294 if (get_midi_node_info (child, ev, chn, additional)) {
295 _midi_rec_enable_control.set_control_type (chn, ev, additional);
297 error << string_compose(_("MIDI rec_enable control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
304 if ((prop = node.property ("diskstream-id")) == 0) {
306 /* some old sessions use the diskstream name rather than the ID */
308 if ((prop = node.property ("diskstream")) == 0) {
309 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
314 if (use_diskstream (prop->value())) {
320 id_t id = strtoull (prop->value().c_str(), 0, 10);
322 if (use_diskstream (id)) {
329 XMLNodeConstIterator niter;
332 nlist = node.children();
333 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
336 if (child->name() == X_("remote_control")) {
337 if ((prop = child->property (X_("id"))) != 0) {
339 sscanf (prop->value().c_str(), "%d", &x);
340 set_remote_control_id (x);
345 pending_state = const_cast<XMLNode*> (&node);
347 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
353 AudioTrack::get_template ()
355 return state (false);
359 AudioTrack::get_state ()
365 AudioTrack::state(bool full_state)
367 XMLNode& root (Route::state(full_state));
368 XMLNode* freeze_node;
371 if (_freeze_record.playlist) {
374 freeze_node = new XMLNode (X_("freeze-info"));
375 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
376 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
377 freeze_node->add_property ("state", buf);
379 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
380 inode = new XMLNode (X_("insert"));
381 snprintf (buf, sizeof (buf), "%" PRIu64, (*i)->id);
382 inode->add_property (X_("id"), buf);
383 inode->add_child_copy ((*i)->state);
385 freeze_node->add_child_nocopy (*inode);
388 root.add_child_nocopy (*freeze_node);
391 /* Alignment: act as a proxy for the diskstream */
393 XMLNode* align_node = new XMLNode (X_("alignment"));
394 switch (diskstream->alignment_style()) {
395 case ExistingMaterial:
396 snprintf (buf, sizeof (buf), X_("existing"));
399 snprintf (buf, sizeof (buf), X_("capture"));
402 align_node->add_property (X_("style"), buf);
403 root.add_child_nocopy (*align_node);
409 MIDI::byte additional;
410 XMLNode* midi_node = 0;
412 XMLNodeList midikids;
414 midikids = root.children ("MIDI");
415 if (!midikids.empty()) {
416 midi_node = midikids.front();
419 midi_node = root.add_child ("MIDI");
422 if (_midi_rec_enable_control.get_control_info (chn, ev, additional) && midi_node) {
424 child = midi_node->add_child ("rec_enable");
425 set_midi_node_info (child, ev, chn, additional);
428 XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
429 snprintf (buf, sizeof (buf), "%d", _remote_control_id);
430 remote_control_node->add_property (X_("id"), buf);
431 root.add_child_nocopy (*remote_control_node);
435 root.add_property (X_("mode"), X_("normal"));
438 root.add_property (X_("mode"), X_("destructive"));
442 /* we don't return diskstream state because we don't
443 own the diskstream exclusively. control of the diskstream
444 state is ceded to the Session, even if we create the
448 snprintf (buf, sizeof (buf), "%" PRIu64, diskstream->id());
449 root.add_property ("diskstream-id", buf);
455 AudioTrack::set_state_part_two ()
459 LocaleGuard lg (X_("POSIX"));
461 /* This is called after all session state has been restored but before
462 have been made ports and connections are established.
465 if (pending_state == 0) {
469 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
472 _freeze_record.have_mementos = false;
473 _freeze_record.state = Frozen;
475 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
478 _freeze_record.insert_info.clear ();
480 if ((prop = fnode->property (X_("playlist"))) != 0) {
481 Playlist* pl = _session.playlist_by_name (prop->value());
483 _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl);
485 _freeze_record.playlist = 0;
486 _freeze_record.state = NoFreeze;
491 if ((prop = fnode->property (X_("state"))) != 0) {
492 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
495 XMLNodeConstIterator citer;
496 XMLNodeList clist = fnode->children();
498 for (citer = clist.begin(); citer != clist.end(); ++citer) {
499 if ((*citer)->name() != X_("insert")) {
503 if ((prop = (*citer)->property (X_("id"))) == 0) {
507 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
509 sscanf (prop->value().c_str(), "%" PRIu64, &frii->id);
510 _freeze_record.insert_info.push_back (frii);
514 /* Alignment: act as a proxy for the diskstream */
516 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
518 if ((prop = fnode->property (X_("style"))) != 0) {
519 if (prop->value() == "existing") {
520 diskstream->set_persistent_align_style (ExistingMaterial);
521 } else if (prop->value() == "capture") {
522 diskstream->set_persistent_align_style (CaptureTime);
530 AudioTrack::n_process_buffers ()
532 return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
536 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)
538 uint32_t nbufs = n_process_buffers ();
539 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
543 AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
544 bool session_state_changing, bool can_record, bool rec_monitors_input)
546 if (n_outputs() == 0) {
551 silence (nframes, offset);
555 if (session_state_changing) {
557 /* XXX is this safe to do against transport state changes? */
559 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
563 diskstream->check_record_status (start_frame, nframes, can_record);
567 if (_have_internal_generator) {
568 /* since the instrument has no input streams,
569 there is no reason to send any signal
575 if (_session.get_auto_input()) {
576 if (Config->get_use_sw_monitoring()) {
577 send_silence = false;
582 if (diskstream->record_enabled()) {
583 if (Config->get_use_sw_monitoring()) {
584 send_silence = false;
594 apply_gain_automation = false;
598 /* if we're sending silence, but we want the meters to show levels for the signal,
602 if (_have_internal_generator) {
603 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
605 if (_meter_point == MeterInput) {
606 just_meter_input (start_frame, end_frame, nframes, offset);
608 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
613 /* we're sending signal, but we may still want to meter the input.
616 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
623 AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
624 bool can_record, bool rec_monitors_input)
629 jack_nframes_t transport_frame;
632 Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
634 // automation snapshot can also be called from the non-rt context
635 // and it uses the redirect list, so we take the lock out here
636 automation_snapshot (start_frame);
640 if (n_outputs() == 0 && _redirects.empty()) {
645 silence (nframes, offset);
649 transport_frame = _session.transport_frame();
651 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
652 /* need to do this so that the diskstream sets its
653 playback distance to zero, thus causing diskstream::commit
656 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
660 apply_gain_automation = false;
662 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
664 silence (nframes, offset);
669 /* special condition applies */
671 if (_meter_point == MeterInput) {
672 just_meter_input (start_frame, end_frame, nframes, offset);
675 if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
677 /* not actually recording, but we want to hear the input material anyway,
678 at least potentially (depending on monitoring options)
681 passthru (start_frame, end_frame, nframes, offset, 0, true);
683 } else if ((b = diskstream->playback_buffer(0)) != 0) {
686 XXX is it true that the earlier test on n_outputs()
687 means that we can avoid checking it again here? i think
688 so, because changing the i/o configuration of an IO
689 requires holding the AudioEngine lock, which we hold
690 while in the process() tree.
694 /* copy the diskstream data to all output buffers */
696 vector<Sample*>& bufs = _session.get_passthru_buffers ();
697 uint32_t limit = n_process_buffers ();
703 for (i = 0, n = 1; i < limit; ++i, ++n) {
704 memcpy (bufs[i], b, sizeof (Sample) * nframes);
705 if (n < diskstream->n_channels()) {
706 tmpb = diskstream->playback_buffer(n);
713 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
715 if (!diskstream->record_enabled() && _session.transport_rolling()) {
716 Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
718 if (am.locked() && gain_automation_playback()) {
719 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
723 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));
726 /* problem with the diskstream; just be quiet for a bit */
727 silence (nframes, offset);
734 AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
735 bool can_record, bool rec_monitors_input)
737 if (n_outputs() == 0 && _redirects.empty()) {
742 silence (nframes, offset);
747 apply_gain_automation = false;
749 silence (nframes, offset);
751 return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
755 AudioTrack::toggle_monitor_input ()
757 for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
758 (*i)->request_monitor_input(!(*i)->monitoring_input());
763 AudioTrack::set_name (string str, void *src)
767 if (record_enabled() && _session.actively_recording()) {
768 /* this messes things up if done while recording */
772 if (diskstream->set_name (str, src)) {
776 /* save state so that the statefile fully reflects any filename changes */
778 if ((ret = IO::set_name (str, src)) == 0) {
779 _session.save_state ("");
785 AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
787 gain_t gain_automation[nframes];
788 gain_t gain_buffer[nframes];
789 float mix_buffer[nframes];
790 RedirectList::iterator i;
791 bool post_fader_work = false;
792 gain_t this_gain = _gain;
793 vector<Sample*>::iterator bi;
796 Glib::RWLock::ReaderLock rlock (redirect_lock);
798 if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
803 bi = buffers.begin();
806 for (; bi != buffers.end(); ++bi, ++n) {
807 if (n < diskstream->n_channels()) {
808 if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
814 /* duplicate last across remaining buffers */
815 memcpy ((*bi), b, sizeof (Sample) * nframes);
820 /* note: only run inserts during export. other layers in the machinery
821 will already have checked that there are no external port inserts.
824 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
827 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
828 switch (insert->placement()) {
830 insert->run (buffers, nbufs, nframes, 0);
833 post_fader_work = true;
839 if (_gain_automation_curve.automation_state() == Play) {
841 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
843 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
845 for (jack_nframes_t n = 0; n < nframes; ++n) {
846 b[n] *= gain_automation[n];
852 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
854 for (jack_nframes_t n = 0; n < nframes; ++n) {
860 if (post_fader_work) {
862 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
863 PluginInsert *insert;
865 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
866 switch ((*i)->placement()) {
870 insert->run (buffers, nbufs, nframes, 0);
881 AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
883 Route::set_latency_delay (longest_session_latency);
884 diskstream->set_roll_delay (_roll_delay);
888 AudioTrack::update_total_latency ()
892 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
893 if ((*i)->active ()) {
894 _own_latency += (*i)->latency ();
898 set_port_latency (_own_latency);
904 AudioTrack::bounce (InterThreadInfo& itt)
906 vector<AudioSource*> srcs;
907 _session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
912 AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
914 vector<AudioSource*> srcs;
915 _session.write_one_audio_track (*this, start, end, false, srcs, itt);
919 AudioTrack::freeze (InterThreadInfo& itt)
922 vector<AudioSource*> srcs;
923 string new_playlist_name;
924 Playlist* new_playlist;
929 if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
935 while (n < (UINT_MAX-1)) {
939 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
941 if (_session.playlist_by_name (candidate) == 0) {
942 new_playlist_name = candidate;
950 if (n == (UINT_MAX-1)) {
951 error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
952 " to create another one"), _freeze_record.playlist->name())
957 if (_session.write_one_audio_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
961 _freeze_record.insert_info.clear ();
962 _freeze_record.have_mementos = true;
965 Glib::RWLock::ReaderLock lm (redirect_lock);
967 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
969 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
971 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
973 frii->insert = insert;
974 frii->id = insert->id();
975 frii->memento = (*r)->get_memento();
977 _freeze_record.insert_info.push_back (frii);
979 /* now deactivate the insert */
981 insert->set_active (false, this);
986 new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
987 region_name = new_playlist_name;
989 /* create a new region from all filesources, keep it private */
991 region = new AudioRegion (srcs, 0, srcs[0]->length(),
993 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
996 new_playlist->set_orig_diskstream_id (diskstream->id());
997 new_playlist->add_region (*region, 0);
998 new_playlist->set_frozen (true);
999 region->set_locked (true);
1001 diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
1002 diskstream->set_record_enabled (false, this);
1004 _freeze_record.state = Frozen;
1005 FreezeChange(); /* EMIT SIGNAL */
1009 AudioTrack::unfreeze ()
1011 if (_freeze_record.playlist) {
1012 diskstream->use_playlist (_freeze_record.playlist);
1014 if (_freeze_record.have_mementos) {
1016 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
1022 Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
1023 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1024 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
1025 if ((*ii)->id == (*i)->id()) {
1026 (*i)->set_state (((*ii)->state));
1033 _freeze_record.playlist = 0;
1036 _freeze_record.state = UnFrozen;
1037 FreezeChange (); /* EMIT SIGNAL */
1040 AudioTrack::FreezeRecord::~FreezeRecord ()
1042 for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
1047 AudioTrack::FreezeState
1048 AudioTrack::freeze_state() const
1050 return _freeze_record.state;
1055 AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
1057 MIDI::channel_t chn;
1061 Route::reset_midi_control (port, on);
1063 _midi_rec_enable_control.get_control_info (chn, ev, extra);
1067 _midi_rec_enable_control.midi_rebind (port, chn);
1071 AudioTrack::send_all_midi_feedback ()
1073 if (_session.get_midi_feedback()) {
1075 Route::send_all_midi_feedback();
1077 _midi_rec_enable_control.send_feedback (record_enabled());
1082 AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s, MIDI::Port* port)
1083 : MIDI::Controllable (port, 0), track (s), setting(false)
1085 last_written = false; /* XXX need a good out of bound value */
1089 AudioTrack::MIDIRecEnableControl::set_value (float val)
1091 bool bval = ((val >= 0.5f) ? true: false);
1094 track.set_record_enable (bval, this);
1099 AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
1102 if (!setting && get_midi_feedback()) {
1103 MIDI::byte val = (MIDI::byte) (value ? 127: 0);
1104 MIDI::channel_t ch = 0;
1105 MIDI::eventType ev = MIDI::none;
1106 MIDI::byte additional = 0;
1107 MIDI::EventTwoBytes data;
1109 if (get_control_info (ch, ev, additional)) {
1110 data.controller_number = additional;
1113 track._session.send_midi_message (get_port(), ev, ch, data);
1120 AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
1122 if (get_midi_feedback()) {
1124 MIDI::channel_t ch = 0;
1125 MIDI::eventType ev = MIDI::none;
1126 MIDI::byte additional = 0;
1128 if (get_control_info (ch, ev, additional)) {
1129 if (val != last_written || force) {
1131 *buf++ = additional; /* controller number */
1132 *buf++ = (MIDI::byte) (val ? 127: 0);
1143 AudioTrack::set_mode (TrackMode m)
1148 diskstream->set_destructive (m == Destructive);