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;
42 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
43 : Route (sess, name, 1, -1, -1, -1, flag),
45 _midi_rec_enable_control (*this, _session.midi_port())
47 AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
49 if (_flags & Hidden) {
50 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Hidden);
52 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Recordable);
55 if (mode == Destructive) {
56 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
59 AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags);
62 _freeze_record.state = NoFreeze;
63 _saved_meter_point = _meter_point;
66 set_diskstream (*ds, this);
68 // session.SMPTEOffsetChanged.connect (mem_fun (*this, &AudioTrack::handle_smpte_offset_change));
70 // we do this even though Route already did it in it's init
71 reset_midi_control (_session.midi_port(), _session.get_midi_control());
75 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
76 : Route (sess, "to be renamed", 0, 0, -1, -1),
78 _midi_rec_enable_control (*this, _session.midi_port())
80 _freeze_record.state = NoFreeze;
83 _saved_meter_point = _meter_point;
85 // we do this even though Route already did it in it's init
86 reset_midi_control (_session.midi_port(), _session.get_midi_control());
89 AudioTrack::~AudioTrack ()
98 AudioTrack::handle_smpte_offset_change ()
105 AudioTrack::deprecated_use_diskstream_connections ()
107 if (diskstream->deprecated_io_node == 0) {
111 const XMLProperty* prop;
112 XMLNode& node (*diskstream->deprecated_io_node);
114 /* don't do this more than once. */
116 diskstream->deprecated_io_node = 0;
118 set_input_minimum (-1);
119 set_input_maximum (-1);
120 set_output_minimum (-1);
121 set_output_maximum (-1);
123 if ((prop = node.property ("gain")) != 0) {
124 set_gain (atof (prop->value().c_str()), this);
125 _gain = _desired_gain;
128 if ((prop = node.property ("input-connection")) != 0) {
129 Connection* c = _session.connection_by_name (prop->value());
132 error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
134 if ((c = _session.connection_by_name (_("in 1"))) == 0) {
135 error << _("No input connections available as a replacement")
139 info << string_compose (_("Connection %1 was not available - \"in 1\" used instead"), prop->value())
144 use_input_connection (*c, this);
146 } else if ((prop = node.property ("inputs")) != 0) {
147 if (set_inputs (prop->value())) {
148 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
157 AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
163 diskstream = &ds.ref();
164 diskstream->set_io (*this);
165 diskstream->set_destructive (_mode == Destructive);
167 if (diskstream->deprecated_io_node) {
169 if (!connecting_legal) {
170 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
172 deprecated_use_diskstream_connections ();
176 diskstream->set_record_enabled (false, this);
177 diskstream->monitor_input (false);
179 ic_connection.disconnect();
180 ic_connection = input_changed.connect (mem_fun (*diskstream, &AudioDiskstream::handle_input_change));
182 diskstream_changed (src); /* EMIT SIGNAL */
188 AudioTrack::use_diskstream (string name)
190 AudioDiskstream *dstream;
192 if ((dstream = _session.diskstream_by_name (name)) == 0) {
193 error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg;
197 return set_diskstream (*dstream, this);
201 AudioTrack::use_diskstream (id_t id)
203 AudioDiskstream *dstream;
205 if ((dstream = _session.diskstream_by_id (id)) == 0) {
206 error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg;
210 return set_diskstream (*dstream, this);
214 AudioTrack::record_enabled () const
216 return diskstream->record_enabled ();
220 AudioTrack::set_record_enable (bool yn, void *src)
222 if (_freeze_record.state == Frozen) {
226 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
227 _mix_group->apply (&AudioTrack::set_record_enable, yn, _mix_group);
231 /* keep track of the meter point as it was before we rec-enabled */
233 if (!diskstream->record_enabled()) {
234 _saved_meter_point = _meter_point;
237 diskstream->set_record_enabled (yn, src);
239 if (diskstream->record_enabled()) {
240 set_meter_point (MeterInput, this);
242 set_meter_point (_saved_meter_point, this);
245 if (_session.get_midi_feedback()) {
246 _midi_rec_enable_control.send_feedback (record_enabled());
252 AudioTrack::set_meter_point (MeterPoint p, void *src)
254 Route::set_meter_point (p, src);
258 AudioTrack::set_state (const XMLNode& node)
260 const XMLProperty *prop;
261 XMLNodeConstIterator iter;
262 XMLNodeList midi_kids;
264 if (Route::set_state (node)) {
268 if ((prop = node.property (X_("mode"))) != 0) {
269 if (prop->value() == X_("normal")) {
271 } else if (prop->value() == X_("destructive")) {
274 warning << string_compose ("unknown audio track mode \"%1\" seen and ignored", prop->value()) << endmsg;
281 midi_kids = node.children ("MIDI");
283 for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
286 XMLNodeConstIterator miter;
289 kids = (*iter)->children ();
291 for (miter = kids.begin(); miter != kids.end(); ++miter) {
295 if (child->name() == "rec_enable") {
297 MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
298 MIDI::byte additional = 0; /* ditto */
299 MIDI::channel_t chn = 0; /* ditto */
301 if (get_midi_node_info (child, ev, chn, additional)) {
302 _midi_rec_enable_control.set_control_type (chn, ev, additional);
304 error << string_compose(_("MIDI rec_enable control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
311 if ((prop = node.property ("diskstream-id")) == 0) {
313 /* some old sessions use the diskstream name rather than the ID */
315 if ((prop = node.property ("diskstream")) == 0) {
316 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
321 if (use_diskstream (prop->value())) {
327 id_t id = strtoull (prop->value().c_str(), 0, 10);
329 if (use_diskstream (id)) {
336 XMLNodeConstIterator niter;
339 nlist = node.children();
340 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
343 if (child->name() == X_("remote_control")) {
344 if ((prop = child->property (X_("id"))) != 0) {
346 sscanf (prop->value().c_str(), "%d", &x);
347 set_remote_control_id (x);
352 pending_state = const_cast<XMLNode*> (&node);
354 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
360 AudioTrack::get_template ()
362 return state (false);
366 AudioTrack::get_state ()
372 AudioTrack::state(bool full_state)
374 XMLNode& root (Route::state(full_state));
375 XMLNode* freeze_node;
378 if (_freeze_record.playlist) {
381 freeze_node = new XMLNode (X_("freeze-info"));
382 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
383 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
384 freeze_node->add_property ("state", buf);
386 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
387 inode = new XMLNode (X_("insert"));
388 snprintf (buf, sizeof (buf), "%" PRIu64, (*i)->id);
389 inode->add_property (X_("id"), buf);
390 inode->add_child_copy ((*i)->state);
392 freeze_node->add_child_nocopy (*inode);
395 root.add_child_nocopy (*freeze_node);
398 /* Alignment: act as a proxy for the diskstream */
400 XMLNode* align_node = new XMLNode (X_("alignment"));
401 switch (diskstream->alignment_style()) {
402 case ExistingMaterial:
403 snprintf (buf, sizeof (buf), X_("existing"));
406 snprintf (buf, sizeof (buf), X_("capture"));
409 align_node->add_property (X_("style"), buf);
410 root.add_child_nocopy (*align_node);
416 MIDI::byte additional;
417 XMLNode* midi_node = 0;
419 XMLNodeList midikids;
421 midikids = root.children ("MIDI");
422 if (!midikids.empty()) {
423 midi_node = midikids.front();
426 midi_node = root.add_child ("MIDI");
429 if (_midi_rec_enable_control.get_control_info (chn, ev, additional) && midi_node) {
431 child = midi_node->add_child ("rec_enable");
432 set_midi_node_info (child, ev, chn, additional);
435 XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
436 snprintf (buf, sizeof (buf), "%d", _remote_control_id);
437 remote_control_node->add_property (X_("id"), buf);
438 root.add_child_nocopy (*remote_control_node);
442 root.add_property (X_("mode"), X_("normal"));
445 root.add_property (X_("mode"), X_("destructive"));
449 /* we don't return diskstream state because we don't
450 own the diskstream exclusively. control of the diskstream
451 state is ceded to the Session, even if we create the
455 snprintf (buf, sizeof (buf), "%" PRIu64, diskstream->id());
456 root.add_property ("diskstream-id", buf);
462 AudioTrack::set_state_part_two ()
466 LocaleGuard lg (X_("POSIX"));
468 /* This is called after all session state has been restored but before
469 have been made ports and connections are established.
472 if (pending_state == 0) {
476 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
479 _freeze_record.have_mementos = false;
480 _freeze_record.state = Frozen;
482 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
485 _freeze_record.insert_info.clear ();
487 if ((prop = fnode->property (X_("playlist"))) != 0) {
488 Playlist* pl = _session.playlist_by_name (prop->value());
490 _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl);
492 _freeze_record.playlist = 0;
493 _freeze_record.state = NoFreeze;
498 if ((prop = fnode->property (X_("state"))) != 0) {
499 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
502 XMLNodeConstIterator citer;
503 XMLNodeList clist = fnode->children();
505 for (citer = clist.begin(); citer != clist.end(); ++citer) {
506 if ((*citer)->name() != X_("insert")) {
510 if ((prop = (*citer)->property (X_("id"))) == 0) {
514 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
516 sscanf (prop->value().c_str(), "%" PRIu64, &frii->id);
517 _freeze_record.insert_info.push_back (frii);
521 /* Alignment: act as a proxy for the diskstream */
523 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
525 if ((prop = fnode->property (X_("style"))) != 0) {
526 if (prop->value() == "existing") {
527 diskstream->set_persistent_align_style (ExistingMaterial);
528 } else if (prop->value() == "capture") {
529 diskstream->set_persistent_align_style (CaptureTime);
537 AudioTrack::n_process_buffers ()
539 return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
543 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)
545 uint32_t nbufs = n_process_buffers ();
546 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
550 AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
551 bool session_state_changing, bool can_record, bool rec_monitors_input)
553 if (n_outputs() == 0) {
558 silence (nframes, offset);
562 if (session_state_changing) {
564 /* XXX is this safe to do against transport state changes? */
566 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
570 diskstream->check_record_status (start_frame, nframes, can_record);
574 if (_have_internal_generator) {
575 /* since the instrument has no input streams,
576 there is no reason to send any signal
582 if (_session.get_auto_input()) {
583 if (Config->get_use_sw_monitoring()) {
584 send_silence = false;
589 if (diskstream->record_enabled()) {
590 if (Config->get_use_sw_monitoring()) {
591 send_silence = false;
601 apply_gain_automation = false;
605 /* if we're sending silence, but we want the meters to show levels for the signal,
609 if (_have_internal_generator) {
610 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
612 if (_meter_point == MeterInput) {
613 just_meter_input (start_frame, end_frame, nframes, offset);
615 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
620 /* we're sending signal, but we may still want to meter the input.
623 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
630 AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
631 bool can_record, bool rec_monitors_input)
636 jack_nframes_t transport_frame;
639 Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
641 // automation snapshot can also be called from the non-rt context
642 // and it uses the redirect list, so we take the lock out here
643 automation_snapshot (start_frame);
647 if (n_outputs() == 0 && _redirects.empty()) {
652 silence (nframes, offset);
656 transport_frame = _session.transport_frame();
658 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
659 /* need to do this so that the diskstream sets its
660 playback distance to zero, thus causing diskstream::commit
663 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
667 apply_gain_automation = false;
669 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
671 silence (nframes, offset);
676 /* special condition applies */
678 if (_meter_point == MeterInput) {
679 just_meter_input (start_frame, end_frame, nframes, offset);
682 if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
684 /* not actually recording, but we want to hear the input material anyway,
685 at least potentially (depending on monitoring options)
688 passthru (start_frame, end_frame, nframes, offset, 0, true);
690 } else if ((b = diskstream->playback_buffer(0)) != 0) {
693 XXX is it true that the earlier test on n_outputs()
694 means that we can avoid checking it again here? i think
695 so, because changing the i/o configuration of an IO
696 requires holding the AudioEngine lock, which we hold
697 while in the process() tree.
701 /* copy the diskstream data to all output buffers */
703 vector<Sample*>& bufs = _session.get_passthru_buffers ();
704 uint32_t limit = n_process_buffers ();
710 for (i = 0, n = 1; i < limit; ++i, ++n) {
711 memcpy (bufs[i], b, sizeof (Sample) * nframes);
712 if (n < diskstream->n_channels()) {
713 tmpb = diskstream->playback_buffer(n);
720 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
722 if (!diskstream->record_enabled() && _session.transport_rolling()) {
723 Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
725 if (am.locked() && gain_automation_playback()) {
726 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
730 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));
733 /* problem with the diskstream; just be quiet for a bit */
734 silence (nframes, offset);
741 AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
742 bool can_record, bool rec_monitors_input)
744 if (n_outputs() == 0 && _redirects.empty()) {
749 silence (nframes, offset);
754 apply_gain_automation = false;
756 silence (nframes, offset);
758 return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
762 AudioTrack::toggle_monitor_input ()
764 for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
765 (*i)->request_monitor_input(!(*i)->monitoring_input());
770 AudioTrack::set_name (string str, void *src)
774 if (record_enabled() && _session.actively_recording()) {
775 /* this messes things up if done while recording */
779 if (diskstream->set_name (str, src)) {
783 /* save state so that the statefile fully reflects any filename changes */
785 if ((ret = IO::set_name (str, src)) == 0) {
786 _session.save_state ("");
792 AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
794 gain_t gain_automation[nframes];
795 gain_t gain_buffer[nframes];
796 float mix_buffer[nframes];
797 RedirectList::iterator i;
798 bool post_fader_work = false;
799 gain_t this_gain = _gain;
800 vector<Sample*>::iterator bi;
803 Glib::RWLock::ReaderLock rlock (redirect_lock);
805 if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
810 bi = buffers.begin();
813 for (; bi != buffers.end(); ++bi, ++n) {
814 if (n < diskstream->n_channels()) {
815 if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
821 /* duplicate last across remaining buffers */
822 memcpy ((*bi), b, sizeof (Sample) * nframes);
827 /* note: only run inserts during export. other layers in the machinery
828 will already have checked that there are no external port inserts.
831 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
834 if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
835 switch (insert->placement()) {
837 insert->run (buffers, nbufs, nframes, 0);
840 post_fader_work = true;
846 if (_gain_automation_curve.automation_state() == Play) {
848 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
850 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
852 for (jack_nframes_t n = 0; n < nframes; ++n) {
853 b[n] *= gain_automation[n];
859 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
861 for (jack_nframes_t n = 0; n < nframes; ++n) {
867 if (post_fader_work) {
869 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
870 PluginInsert *insert;
872 if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
873 switch ((*i)->placement()) {
877 insert->run (buffers, nbufs, nframes, 0);
888 AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
890 Route::set_latency_delay (longest_session_latency);
891 diskstream->set_roll_delay (_roll_delay);
895 AudioTrack::update_total_latency ()
899 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
900 if ((*i)->active ()) {
901 _own_latency += (*i)->latency ();
905 set_port_latency (_own_latency);
911 AudioTrack::bounce (InterThreadInfo& itt)
913 vector<AudioSource*> srcs;
914 _session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
919 AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
921 vector<AudioSource*> srcs;
922 _session.write_one_audio_track (*this, start, end, false, srcs, itt);
926 AudioTrack::freeze (InterThreadInfo& itt)
929 vector<AudioSource*> srcs;
930 string new_playlist_name;
931 Playlist* new_playlist;
936 if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
942 while (n < (UINT_MAX-1)) {
946 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
948 if (_session.playlist_by_name (candidate) == 0) {
949 new_playlist_name = candidate;
957 if (n == (UINT_MAX-1)) {
958 error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
959 " to create another one"), _freeze_record.playlist->name())
964 if (_session.write_one_audio_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
968 _freeze_record.insert_info.clear ();
969 _freeze_record.have_mementos = true;
972 Glib::RWLock::ReaderLock lm (redirect_lock);
974 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
976 if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
978 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state());
980 frii->insert = insert;
981 frii->id = insert->id();
982 frii->memento = (*r)->get_memento();
984 _freeze_record.insert_info.push_back (frii);
986 /* now deactivate the insert */
988 insert->set_active (false, this);
993 new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
994 region_name = new_playlist_name;
996 /* create a new region from all filesources, keep it private */
998 region = new AudioRegion (srcs, 0, srcs[0]->length(),
1000 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
1003 new_playlist->set_orig_diskstream_id (diskstream->id());
1004 new_playlist->add_region (*region, 0);
1005 new_playlist->set_frozen (true);
1006 region->set_locked (true);
1008 diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
1009 diskstream->set_record_enabled (false, this);
1011 _freeze_record.state = Frozen;
1012 FreezeChange(); /* EMIT SIGNAL */
1016 AudioTrack::unfreeze ()
1018 if (_freeze_record.playlist) {
1019 diskstream->use_playlist (_freeze_record.playlist);
1021 if (_freeze_record.have_mementos) {
1023 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
1029 Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
1030 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1031 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
1032 if ((*ii)->id == (*i)->id()) {
1033 (*i)->set_state (((*ii)->state));
1040 _freeze_record.playlist = 0;
1043 _freeze_record.state = UnFrozen;
1044 FreezeChange (); /* EMIT SIGNAL */
1047 AudioTrack::FreezeRecord::~FreezeRecord ()
1049 for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
1054 AudioTrack::FreezeState
1055 AudioTrack::freeze_state() const
1057 return _freeze_record.state;
1062 AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
1064 MIDI::channel_t chn;
1068 Route::reset_midi_control (port, on);
1070 _midi_rec_enable_control.get_control_info (chn, ev, extra);
1074 _midi_rec_enable_control.midi_rebind (port, chn);
1078 AudioTrack::send_all_midi_feedback ()
1080 if (_session.get_midi_feedback()) {
1082 Route::send_all_midi_feedback();
1084 _midi_rec_enable_control.send_feedback (record_enabled());
1089 AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s, MIDI::Port* port)
1090 : MIDI::Controllable (port, 0), track (s), setting(false)
1092 last_written = false; /* XXX need a good out of bound value */
1096 AudioTrack::MIDIRecEnableControl::set_value (float val)
1098 bool bval = ((val >= 0.5f) ? true: false);
1101 track.set_record_enable (bval, this);
1106 AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
1109 if (!setting && get_midi_feedback()) {
1110 MIDI::byte val = (MIDI::byte) (value ? 127: 0);
1111 MIDI::channel_t ch = 0;
1112 MIDI::eventType ev = MIDI::none;
1113 MIDI::byte additional = 0;
1114 MIDI::EventTwoBytes data;
1116 if (get_control_info (ch, ev, additional)) {
1117 data.controller_number = additional;
1120 track._session.send_midi_message (get_port(), ev, ch, data);
1127 AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
1129 if (get_midi_feedback()) {
1131 MIDI::channel_t ch = 0;
1132 MIDI::eventType ev = MIDI::none;
1133 MIDI::byte additional = 0;
1135 if (get_control_info (ch, ev, additional)) {
1136 if (val != last_written || force) {
1138 *buf++ = additional; /* controller number */
1139 *buf++ = (MIDI::byte) (val ? 127: 0);
1150 AudioTrack::set_mode (TrackMode m)
1155 diskstream->set_destructive (m == Destructive);