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 <sigc++/retype.h>
21 #include <sigc++/retype_return.h>
22 #include <sigc++/bind.h>
24 #include <pbd/error.h>
25 #include <pbd/enumwriter.h>
27 #include <ardour/audio_track.h>
28 #include <ardour/audio_diskstream.h>
29 #include <ardour/session.h>
30 #include <ardour/io_processor.h>
31 #include <ardour/audioregion.h>
32 #include <ardour/audiosource.h>
33 #include <ardour/region_factory.h>
34 #include <ardour/route_group_specialized.h>
35 #include <ardour/processor.h>
36 #include <ardour/plugin_insert.h>
37 #include <ardour/audioplaylist.h>
38 #include <ardour/playlist_factory.h>
39 #include <ardour/panner.h>
40 #include <ardour/utils.h>
41 #include <ardour/buffer_set.h>
42 #include <ardour/audio_buffer.h>
43 #include <ardour/internal_send.h>
47 using namespace ARDOUR;
50 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
51 : Track (sess, name, flag, mode)
53 AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
55 if (_flags & Hidden) {
56 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Hidden);
58 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Recordable);
61 if (mode == Destructive) {
62 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
65 boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name, dflags));
67 _session.add_diskstream (ds);
69 _session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
71 set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
74 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
77 _set_state (node, false);
79 _session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
82 AudioTrack::~AudioTrack ()
87 AudioTrack::catch_up_on_busses (RouteList& added)
93 for (RouteList::iterator x = added.begin(); x != added.end(); ++x) {
94 if (boost::dynamic_pointer_cast<Track>(*x) == 0 && (*x)->default_type() == DataType::AUDIO) {
96 if (!(*x)->is_master() && !(*x)->is_control()) {
97 add_internal_send (*x);
104 AudioTrack::add_internal_send (boost::shared_ptr<Route> r)
106 boost::shared_ptr<InternalSend> is (new InternalSend (_session, PreFader, r));
108 cerr << name() << " Adding processor\n";
110 add_processor (is, 0);
112 cerr << "After add, we have " << _processors.size() << endl;
114 /* note: if adding failed, the InternalSend will be cleaned up automatically when
115 the shared_ptr goes out of scope.
120 AudioTrack::set_mode (TrackMode m)
124 if (_diskstream->set_destructive (m == Destructive)) {
130 TrackModeChanged (); /* EMIT SIGNAL */
137 AudioTrack::can_use_mode (TrackMode m, bool& bounce_required)
141 bounce_required = false;
146 return _diskstream->can_become_destructive (bounce_required);
151 AudioTrack::deprecated_use_diskstream_connections ()
153 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
155 if (diskstream->deprecated_io_node == 0) {
159 const XMLProperty* prop;
160 XMLNode& node (*diskstream->deprecated_io_node);
162 /* don't do this more than once. */
164 diskstream->deprecated_io_node = 0;
166 set_input_minimum (ChanCount::ZERO);
167 set_input_maximum (ChanCount::INFINITE);
168 set_output_minimum (ChanCount::ZERO);
169 set_output_maximum (ChanCount::INFINITE);
171 if ((prop = node.property ("gain")) != 0) {
172 set_gain (atof (prop->value().c_str()), this);
173 _gain = _desired_gain;
176 if ((prop = node.property ("input-connection")) != 0) {
177 boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
180 error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
182 if ((c = _session.bundle_by_name (_("in 1"))) == 0) {
183 error << _("No input bundles available as a replacement")
187 info << string_compose (_("Bundle %1 was not available - \"in 1\" used instead"), prop->value())
192 connect_input_ports_to_bundle (c, this);
194 } else if ((prop = node.property ("inputs")) != 0) {
195 if (set_inputs (prop->value())) {
196 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
205 AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
208 _diskstream->set_io (*this);
209 _diskstream->set_destructive (_mode == Destructive);
211 if (audio_diskstream()->deprecated_io_node) {
213 if (!connecting_legal) {
214 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
216 deprecated_use_diskstream_connections ();
220 _diskstream->set_record_enabled (false);
221 _diskstream->monitor_input (false);
223 ic_connection.disconnect();
224 ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
226 DiskstreamChanged (); /* EMIT SIGNAL */
232 AudioTrack::use_diskstream (string name)
234 boost::shared_ptr<AudioDiskstream> dstream;
236 if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream>(_session.diskstream_by_name (name))) == 0) {
237 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
241 return set_diskstream (dstream, this);
245 AudioTrack::use_diskstream (const PBD::ID& id)
247 boost::shared_ptr<AudioDiskstream> dstream;
249 if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream> (_session.diskstream_by_id (id))) == 0) {
250 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
254 return set_diskstream (dstream, this);
257 boost::shared_ptr<AudioDiskstream>
258 AudioTrack::audio_diskstream() const
260 return boost::dynamic_pointer_cast<AudioDiskstream>(_diskstream);
264 AudioTrack::set_state (const XMLNode& node)
266 return _set_state (node, true);
270 AudioTrack::_set_state (const XMLNode& node, bool call_base)
272 const XMLProperty *prop;
273 XMLNodeConstIterator iter;
276 if (Route::_set_state (node, call_base)) {
281 if ((prop = node.property (X_("mode"))) != 0) {
282 _mode = TrackMode (string_2_enum (prop->value(), _mode));
287 if ((prop = node.property ("diskstream-id")) == 0) {
289 /* some old sessions use the diskstream name rather than the ID */
291 if ((prop = node.property ("diskstream")) == 0) {
292 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
297 if (use_diskstream (prop->value())) {
303 PBD::ID id (prop->value());
305 if (use_diskstream (id)) {
312 XMLNodeConstIterator niter;
315 nlist = node.children();
316 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
319 if (child->name() == X_("recenable")) {
320 _rec_enable_control->set_state (*child);
321 _session.add_controllable (_rec_enable_control);
325 pending_state = const_cast<XMLNode*> (&node);
327 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
333 AudioTrack::state(bool full_state)
335 XMLNode& root (Route::state(full_state));
336 XMLNode* freeze_node;
339 if (_freeze_record.playlist) {
342 freeze_node = new XMLNode (X_("freeze-info"));
343 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
344 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
346 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
347 inode = new XMLNode (X_("processor"));
348 (*i)->id.print (buf, sizeof (buf));
349 inode->add_property (X_("id"), buf);
350 inode->add_child_copy ((*i)->state);
352 freeze_node->add_child_nocopy (*inode);
355 root.add_child_nocopy (*freeze_node);
358 /* Alignment: act as a proxy for the diskstream */
360 XMLNode* align_node = new XMLNode (X_("alignment"));
361 AlignStyle as = _diskstream->alignment_style ();
362 align_node->add_property (X_("style"), enum_2_string (as));
363 root.add_child_nocopy (*align_node);
365 root.add_property (X_("mode"), enum_2_string (_mode));
367 /* we don't return diskstream state because we don't
368 own the diskstream exclusively. control of the diskstream
369 state is ceded to the Session, even if we create the
373 _diskstream->id().print (buf, sizeof (buf));
374 root.add_property ("diskstream-id", buf);
376 root.add_child_nocopy (_rec_enable_control->get_state());
382 AudioTrack::set_state_part_two ()
386 LocaleGuard lg (X_("POSIX"));
388 /* This is called after all session state has been restored but before
389 have been made ports and connections are established.
392 if (pending_state == 0) {
396 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
399 _freeze_record.have_mementos = false;
400 _freeze_record.state = Frozen;
402 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
405 _freeze_record.processor_info.clear ();
407 if ((prop = fnode->property (X_("playlist"))) != 0) {
408 boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value());
410 _freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
412 _freeze_record.playlist.reset ();
413 _freeze_record.state = NoFreeze;
418 if ((prop = fnode->property (X_("state"))) != 0) {
419 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
422 XMLNodeConstIterator citer;
423 XMLNodeList clist = fnode->children();
425 for (citer = clist.begin(); citer != clist.end(); ++citer) {
426 if ((*citer)->name() != X_("processor")) {
430 if ((prop = (*citer)->property (X_("id"))) == 0) {
434 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
435 boost::shared_ptr<Processor>());
436 frii->id = prop->value ();
437 _freeze_record.processor_info.push_back (frii);
441 /* Alignment: act as a proxy for the diskstream */
443 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
445 if ((prop = fnode->property (X_("style"))) != 0) {
447 /* fix for older sessions from before EnumWriter */
451 if (prop->value() == "capture") {
452 pstr = "CaptureTime";
453 } else if (prop->value() == "existing") {
454 pstr = "ExistingMaterial";
456 pstr = prop->value();
459 AlignStyle as = AlignStyle (string_2_enum (pstr, as));
460 _diskstream->set_persistent_align_style (as);
467 AudioTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
468 bool session_state_changing, bool can_record, bool rec_monitors_input)
470 if (n_outputs().n_total() == 0) {
475 silence (nframes, offset);
479 if (session_state_changing) {
481 /* XXX is this safe to do against transport state changes? */
483 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
487 audio_diskstream()->check_record_status (start_frame, nframes, can_record);
491 if (_have_internal_generator) {
492 /* since the instrument has no input streams,
493 there is no reason to send any signal
499 if (!Config->get_tape_machine_mode()) {
501 ADATs work in a strange way..
502 they monitor input always when stopped.and auto-input is engaged.
504 if ((Config->get_monitoring_model() == SoftwareMonitoring) && (Config->get_auto_input () || _diskstream->record_enabled())) {
505 send_silence = false;
511 Other machines switch to input on stop if the track is record enabled,
512 regardless of the auto input setting (auto input only changes the
513 monitoring state when the transport is rolling)
515 if ((Config->get_monitoring_model() == SoftwareMonitoring) && _diskstream->record_enabled()) {
516 send_silence = false;
523 apply_gain_automation = false;
527 /* if we're sending silence, but we want the meters to show levels for the signal,
531 if (_have_internal_generator) {
532 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
534 if (_meter_point == MeterInput) {
535 just_meter_input (start_frame, end_frame, nframes, offset);
537 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
542 /* we're sending signal, but we may still want to meter the input.
545 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
552 AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick,
553 bool can_record, bool rec_monitors_input)
558 nframes_t transport_frame;
559 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
562 Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
564 // automation snapshot can also be called from the non-rt context
565 // and it uses the redirect list, so we take the lock out here
566 automation_snapshot (start_frame, false);
571 if (n_outputs().n_total() == 0 && _processors.empty()) {
576 silence (nframes, offset);
580 transport_frame = _session.transport_frame();
582 prepare_inputs( nframes, offset );
584 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
585 /* need to do this so that the diskstream sets its
586 playback distance to zero, thus causing diskstream::commit
589 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
593 apply_gain_automation = false;
595 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
597 silence (nframes, offset);
602 /* special condition applies */
604 if (_meter_point == MeterInput) {
605 just_meter_input (start_frame, end_frame, nframes, offset);
608 if (diskstream->record_enabled() && !can_record && !Config->get_auto_input()) {
610 /* not actually recording, but we want to hear the input material anyway,
611 at least potentially (depending on monitoring options)
614 passthru (start_frame, end_frame, nframes, offset, 0, true);
616 } else if ((b = diskstream->playback_buffer(0)) != 0) {
619 XXX is it true that the earlier test on n_outputs()
620 means that we can avoid checking it again here? i think
621 so, because changing the i/o configuration of an IO
622 requires holding the AudioEngine lock, which we hold
623 while in the process() tree.
627 /* copy the diskstream data to all output buffers */
629 size_t limit = n_process_buffers().n_audio();
630 BufferSet& bufs = _session.get_scratch_buffers ();
631 const size_t blimit = bufs.count().n_audio();
636 if (limit > blimit) {
638 /* example case: auditioner configured for stereo output,
639 but loaded with an 8 channel file. there are only
640 2 passthrough buffers, but n_process_buffers() will
643 arbitrary decision: map all channels in the diskstream
644 to the outputs available.
647 float scaling = limit/blimit;
649 for (i = 0, n = 1; i < blimit; ++i, ++n) {
651 /* first time through just copy a channel into
655 Sample* bb = bufs.get_audio (i).data();
657 for (nframes_t xx = 0; xx < nframes; ++xx) {
658 bb[xx] = b[xx] * scaling;
661 if (n < diskstream->n_channels().n_audio()) {
662 tmpb = diskstream->playback_buffer(n);
669 for (;i < limit; ++i, ++n) {
671 /* for all remaining channels, sum with existing
672 data in the output buffers
675 bufs.get_audio (i%blimit).accumulate_with_gain_from (b, nframes, 0, scaling);
677 if (n < diskstream->n_channels().n_audio()) {
678 tmpb = diskstream->playback_buffer(n);
689 for (i = 0, n = 1; i < blimit; ++i, ++n) {
690 memcpy (bufs.get_audio (i).data(), b, sizeof (Sample) * nframes);
691 if (n < diskstream->n_channels().n_audio()) {
692 tmpb = diskstream->playback_buffer(n);
700 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
702 if (!diskstream->record_enabled() && _session.transport_rolling()) {
703 Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
705 if (am.locked() && gain_control()->automation_playback()) {
706 apply_gain_automation = gain_control()->list()->curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
710 process_output_buffers (bufs, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
713 /* problem with the diskstream; just be quiet for a bit */
714 silence (nframes, offset);
721 AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
722 bool can_record, bool rec_monitors_input)
724 if (n_outputs().n_total() == 0 && _processors.empty()) {
729 silence (nframes, offset);
734 apply_gain_automation = false;
736 silence (nframes, offset);
738 return audio_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
742 AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes)
744 gain_t gain_automation[nframes];
745 gain_t gain_buffer[nframes];
746 float mix_buffer[nframes];
747 ProcessorList::iterator i;
748 bool post_fader_work = false;
749 gain_t this_gain = _gain;
750 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
752 Glib::RWLock::ReaderLock rlock (_processor_lock);
754 boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
757 assert(buffers.get_audio(0).capacity() >= nframes);
759 if (apl->read (buffers.get_audio(0).data(), mix_buffer, gain_buffer, start, nframes) != nframes) {
763 assert(buffers.count().n_audio() >= 1);
765 Sample* b = buffers.get_audio(0).data();
766 BufferSet::audio_iterator bi = buffers.audio_begin();
768 for ( ; bi != buffers.audio_end(); ++bi, ++n) {
769 if (n < diskstream->n_channels().n_audio()) {
770 if (apl->read (bi->data(), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
776 /* duplicate last across remaining buffers */
777 memcpy (bi->data(), b, sizeof (Sample) * nframes);
782 /* note: only run processors during export. other layers in the machinery
783 will already have checked that there are no external port processors.
786 for (i = _processors.begin(); i != _processors.end(); ++i) {
787 boost::shared_ptr<Processor> processor;
789 if ((processor = boost::dynamic_pointer_cast<Processor>(*i)) != 0) {
790 switch (processor->placement()) {
792 processor->run_in_place (buffers, start, start+nframes, nframes, 0);
795 post_fader_work = true;
801 if (gain_control()->automation_state() == Play) {
803 gain_control()->list()->curve().get_vector (start, start + nframes, gain_automation, nframes);
805 for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
806 Sample *b = bi->data();
807 for (nframes_t n = 0; n < nframes; ++n) {
808 b[n] *= gain_automation[n];
814 for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
815 Sample *b = bi->data();
816 for (nframes_t n = 0; n < nframes; ++n) {
822 if (post_fader_work) {
824 for (i = _processors.begin(); i != _processors.end(); ++i) {
825 boost::shared_ptr<PluginInsert> processor;
827 if ((processor = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
828 switch ((*i)->placement()) {
832 processor->run_in_place (buffers, start, start+nframes, nframes, 0);
842 boost::shared_ptr<Region>
843 AudioTrack::bounce (InterThreadInfo& itt)
845 vector<boost::shared_ptr<Source> > srcs;
846 return _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), false, srcs, itt);
849 boost::shared_ptr<Region>
850 AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt)
852 vector<boost::shared_ptr<Source> > srcs;
853 return _session.write_one_track (*this, start, end, false, srcs, itt);
857 AudioTrack::freeze (InterThreadInfo& itt)
859 vector<boost::shared_ptr<Source> > srcs;
860 string new_playlist_name;
861 boost::shared_ptr<Playlist> new_playlist;
864 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
866 if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) {
872 while (n < (UINT_MAX-1)) {
876 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
878 if (_session.playlist_by_name (candidate) == 0) {
879 new_playlist_name = candidate;
887 if (n == (UINT_MAX-1)) {
888 error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
889 " to create another one"), _freeze_record.playlist->name())
894 boost::shared_ptr<Region> res;
896 if ((res = _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) {
900 _freeze_record.processor_info.clear ();
901 _freeze_record.have_mementos = true;
904 Glib::RWLock::ReaderLock lm (_processor_lock);
906 for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); ++r) {
908 boost::shared_ptr<Processor> processor;
910 if ((processor = boost::dynamic_pointer_cast<Processor>(*r)) != 0) {
912 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo ((*r)->get_state(), processor);
914 frii->id = processor->id();
916 _freeze_record.processor_info.push_back (frii);
918 /* now deactivate the processor */
920 processor->deactivate ();
921 _session.set_dirty ();
926 new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
928 _freeze_record.gain = _gain;
929 _freeze_record.gain_automation_state = _gain_control->automation_state();
930 _freeze_record.pan_automation_state = _panner->automation_state();
932 region_name = new_playlist_name;
934 /* create a new region from all filesources, keep it private */
936 boost::shared_ptr<Region> region (RegionFactory::create (srcs, 0, srcs[0]->length(),
938 (Region::Flag) (Region::WholeFile|Region::DefaultFlags),
941 new_playlist->set_orig_diskstream_id (diskstream->id());
942 new_playlist->add_region (region, _session.current_start_frame());
943 new_playlist->set_frozen (true);
944 region->set_locked (true);
946 diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
947 diskstream->set_record_enabled (false);
949 /* reset stuff that has already been accounted for in the freeze process */
951 set_gain (1.0, this);
952 _gain_control->set_automation_state (Off);
953 _panner->set_automation_state (Off);
955 _freeze_record.state = Frozen;
956 FreezeChange(); /* EMIT SIGNAL */
960 AudioTrack::unfreeze ()
962 if (_freeze_record.playlist) {
963 audio_diskstream()->use_playlist (_freeze_record.playlist);
965 if (_freeze_record.have_mementos) {
967 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
973 Glib::RWLock::ReaderLock lm (_processor_lock); // should this be a write lock? jlc
974 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
975 for (vector<FreezeRecordProcessorInfo*>::iterator ii = _freeze_record.processor_info.begin(); ii != _freeze_record.processor_info.end(); ++ii) {
976 if ((*ii)->id == (*i)->id()) {
977 (*i)->set_state (((*ii)->state));
984 _freeze_record.playlist.reset ();
985 set_gain (_freeze_record.gain, this);
986 _gain_control->set_automation_state (_freeze_record.gain_automation_state);
987 _panner->set_automation_state (_freeze_record.pan_automation_state);
990 _freeze_record.state = UnFrozen;
991 FreezeChange (); /* EMIT SIGNAL */