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)
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 = _session.diskstream_by_name (name)) == 0) {
194 error << string_compose(_("AudioTrack: 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 = _session.diskstream_by_id (id)) == 0) {
207 error << string_compose(_("AudioTrack: 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);
806 if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
811 bi = buffers.begin();
814 for (; bi != buffers.end(); ++bi, ++n) {
815 if (n < diskstream->n_channels()) {
816 if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
822 /* duplicate last across remaining buffers */
823 memcpy ((*bi), b, sizeof (Sample) * nframes);
828 /* note: only run inserts during export. other layers in the machinery
829 will already have checked that there are no external port inserts.
832 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
835 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
836 switch (insert->placement()) {
838 insert->run (buffers, nbufs, nframes, 0);
841 post_fader_work = true;
847 if (_gain_automation_curve.automation_state() == Play) {
849 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
851 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
853 for (jack_nframes_t n = 0; n < nframes; ++n) {
854 b[n] *= gain_automation[n];
860 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
862 for (jack_nframes_t n = 0; n < nframes; ++n) {
868 if (post_fader_work) {
870 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
871 PluginInsert *insert;
873 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
874 switch ((*i)->placement()) {
878 insert->run (buffers, nbufs, nframes, 0);
889 AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
891 Route::set_latency_delay (longest_session_latency);
892 diskstream->set_roll_delay (_roll_delay);
896 AudioTrack::update_total_latency ()
900 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
901 if ((*i)->active ()) {
902 _own_latency += (*i)->latency ();
906 set_port_latency (_own_latency);
912 AudioTrack::bounce (InterThreadInfo& itt)
914 vector<AudioSource*> srcs;
915 _session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
920 AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
922 vector<AudioSource*> srcs;
923 _session.write_one_audio_track (*this, start, end, false, srcs, itt);
927 AudioTrack::freeze (InterThreadInfo& itt)
930 vector<AudioSource*> srcs;
931 string new_playlist_name;
932 Playlist* new_playlist;
937 if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
943 while (n < (UINT_MAX-1)) {
947 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
949 if (_session.playlist_by_name (candidate) == 0) {
950 new_playlist_name = candidate;
958 if (n == (UINT_MAX-1)) {
959 error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
960 " to create another one"), _freeze_record.playlist->name())
965 if (_session.write_one_audio_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
969 _freeze_record.insert_info.clear ();
970 _freeze_record.have_mementos = true;
973 Glib::RWLock::ReaderLock lm (redirect_lock);
975 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
977 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
979 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
981 frii->insert = insert;
982 frii->id = insert->id();
983 frii->memento = (*r)->get_memento();
985 _freeze_record.insert_info.push_back (frii);
987 /* now deactivate the insert */
989 insert->set_active (false, this);
994 new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
995 region_name = new_playlist_name;
997 /* create a new region from all filesources, keep it private */
999 region = new AudioRegion (srcs, 0, srcs[0]->length(),
1001 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
1004 new_playlist->set_orig_diskstream_id (diskstream->id());
1005 new_playlist->add_region (*region, 0);
1006 new_playlist->set_frozen (true);
1007 region->set_locked (true);
1009 diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
1010 diskstream->set_record_enabled (false, this);
1012 _freeze_record.state = Frozen;
1013 FreezeChange(); /* EMIT SIGNAL */
1017 AudioTrack::unfreeze ()
1019 if (_freeze_record.playlist) {
1020 diskstream->use_playlist (_freeze_record.playlist);
1022 if (_freeze_record.have_mementos) {
1024 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
1030 Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
1031 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1032 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
1033 if ((*ii)->id == (*i)->id()) {
1034 (*i)->set_state (((*ii)->state));
1041 _freeze_record.playlist = 0;
1044 _freeze_record.state = UnFrozen;
1045 FreezeChange (); /* EMIT SIGNAL */
1048 AudioTrack::FreezeRecord::~FreezeRecord ()
1050 for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
1055 AudioTrack::FreezeState
1056 AudioTrack::freeze_state() const
1058 return _freeze_record.state;
1063 AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
1065 MIDI::channel_t chn;
1069 Route::reset_midi_control (port, on);
1071 _midi_rec_enable_control.get_control_info (chn, ev, extra);
1075 _midi_rec_enable_control.midi_rebind (port, chn);
1079 AudioTrack::send_all_midi_feedback ()
1081 if (_session.get_midi_feedback()) {
1083 Route::send_all_midi_feedback();
1085 _midi_rec_enable_control.send_feedback (record_enabled());
1090 AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s, MIDI::Port* port)
1091 : MIDI::Controllable (port, 0), track (s), setting(false)
1093 last_written = false; /* XXX need a good out of bound value */
1097 AudioTrack::MIDIRecEnableControl::set_value (float val)
1099 bool bval = ((val >= 0.5f) ? true: false);
1102 track.set_record_enable (bval, this);
1107 AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
1110 if (!setting && get_midi_feedback()) {
1111 MIDI::byte val = (MIDI::byte) (value ? 127: 0);
1112 MIDI::channel_t ch = 0;
1113 MIDI::eventType ev = MIDI::none;
1114 MIDI::byte additional = 0;
1115 MIDI::EventTwoBytes data;
1117 if (get_control_info (ch, ev, additional)) {
1118 data.controller_number = additional;
1121 track._session.send_midi_message (get_port(), ev, ch, data);
1128 AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
1130 if (get_midi_feedback()) {
1132 MIDI::channel_t ch = 0;
1133 MIDI::eventType ev = MIDI::none;
1134 MIDI::byte additional = 0;
1136 if (get_control_info (ch, ev, additional)) {
1137 if (val != last_written || force) {
1139 *buf++ = additional; /* controller number */
1140 *buf++ = (MIDI::byte) (val ? 127: 0);
1151 AudioTrack::set_mode (TrackMode m)
1156 diskstream->set_destructive (m == Destructive);