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 "evoral/Curve.hpp"
29 #include "ardour/audio_track.h"
30 #include "ardour/audio_diskstream.h"
31 #include "ardour/session.h"
32 #include "ardour/io_processor.h"
33 #include "ardour/audioregion.h"
34 #include "ardour/audiosource.h"
35 #include "ardour/region_factory.h"
36 #include "ardour/route_group_specialized.h"
37 #include "ardour/processor.h"
38 #include "ardour/plugin_insert.h"
39 #include "ardour/audioplaylist.h"
40 #include "ardour/playlist_factory.h"
41 #include "ardour/panner.h"
42 #include "ardour/utils.h"
43 #include "ardour/buffer_set.h"
44 #include "ardour/audio_buffer.h"
48 using namespace ARDOUR;
51 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
52 : Track (sess, name, flag, mode)
54 use_new_diskstream ();
57 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
60 _set_state (node, false);
63 AudioTrack::~AudioTrack ()
68 AudioTrack::use_new_diskstream ()
70 AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
72 if (_flags & Hidden) {
73 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Hidden);
75 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Recordable);
78 if (_mode == Destructive) {
79 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
82 boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name(), dflags));
84 _session.add_diskstream (ds);
86 set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
90 AudioTrack::set_mode (TrackMode m)
94 if (_diskstream->set_destructive (m == Destructive)) {
100 TrackModeChanged (); /* EMIT SIGNAL */
107 AudioTrack::can_use_mode (TrackMode m, bool& bounce_required)
111 bounce_required = false;
116 return _diskstream->can_become_destructive (bounce_required);
121 AudioTrack::deprecated_use_diskstream_connections ()
123 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
125 if (diskstream->deprecated_io_node == 0) {
129 const XMLProperty* prop;
130 XMLNode& node (*diskstream->deprecated_io_node);
132 /* don't do this more than once. */
134 diskstream->deprecated_io_node = 0;
136 set_input_minimum (ChanCount::ZERO);
137 set_input_maximum (ChanCount::INFINITE);
138 set_output_minimum (ChanCount::ZERO);
139 set_output_maximum (ChanCount::INFINITE);
141 if ((prop = node.property ("gain")) != 0) {
142 set_gain (atof (prop->value().c_str()), this);
143 _gain = _desired_gain;
146 if ((prop = node.property ("input-connection")) != 0) {
147 boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
150 error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
152 if ((c = _session.bundle_by_name (_("in 1"))) == 0) {
153 error << _("No input bundles available as a replacement")
157 info << string_compose (_("Bundle %1 was not available - \"in 1\" used instead"), prop->value())
162 connect_input_ports_to_bundle (c, this);
164 } else if ((prop = node.property ("inputs")) != 0) {
165 if (set_inputs (prop->value())) {
166 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
175 AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
178 _diskstream->set_io (*this);
179 _diskstream->set_destructive (_mode == Destructive);
181 if (audio_diskstream()->deprecated_io_node) {
183 if (!connecting_legal) {
184 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
186 deprecated_use_diskstream_connections ();
190 _diskstream->set_record_enabled (false);
191 _diskstream->monitor_input (false);
193 ic_connection.disconnect();
194 ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
196 DiskstreamChanged (); /* EMIT SIGNAL */
202 AudioTrack::use_diskstream (string name)
204 boost::shared_ptr<AudioDiskstream> dstream;
206 if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream>(_session.diskstream_by_name (name))) == 0) {
207 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
211 return set_diskstream (dstream, this);
215 AudioTrack::use_diskstream (const PBD::ID& id)
217 boost::shared_ptr<AudioDiskstream> dstream;
219 if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream> (_session.diskstream_by_id (id))) == 0) {
220 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
224 return set_diskstream (dstream, this);
227 boost::shared_ptr<AudioDiskstream>
228 AudioTrack::audio_diskstream() const
230 return boost::dynamic_pointer_cast<AudioDiskstream>(_diskstream);
234 AudioTrack::set_state (const XMLNode& node)
236 return _set_state (node, true);
240 AudioTrack::_set_state (const XMLNode& node, bool call_base)
242 const XMLProperty *prop;
243 XMLNodeConstIterator iter;
246 if (Route::_set_state (node, call_base)) {
251 if ((prop = node.property (X_("mode"))) != 0) {
252 _mode = TrackMode (string_2_enum (prop->value(), _mode));
257 if ((prop = node.property ("diskstream-id")) == 0) {
259 /* some old sessions use the diskstream name rather than the ID */
261 if ((prop = node.property ("diskstream")) == 0) {
262 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
267 if (use_diskstream (prop->value())) {
273 PBD::ID id (prop->value());
276 /* this wierd hack is used when creating tracks from a template. there isn't
277 a particularly good time to interpose between setting the first part of
278 the track state (notably Route::set_state() and the track mode), and the
279 second part (diskstream stuff). So, we have a special ID for the diskstream
280 that means "you should create a new diskstream here, not look for
285 use_new_diskstream ();
286 } else if (use_diskstream (id)) {
293 XMLNodeConstIterator niter;
296 nlist = node.children();
297 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
300 if (child->name() == X_("recenable")) {
301 _rec_enable_control->set_state (*child);
302 _session.add_controllable (_rec_enable_control);
306 pending_state = const_cast<XMLNode*> (&node);
308 if (_session.state_of_the_state() & Session::Loading) {
309 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
311 set_state_part_two ();
318 AudioTrack::state(bool full_state)
320 XMLNode& root (Route::state(full_state));
321 XMLNode* freeze_node;
324 if (_freeze_record.playlist) {
327 freeze_node = new XMLNode (X_("freeze-info"));
328 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
329 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
331 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
332 inode = new XMLNode (X_("processor"));
333 (*i)->id.print (buf, sizeof (buf));
334 inode->add_property (X_("id"), buf);
335 inode->add_child_copy ((*i)->state);
337 freeze_node->add_child_nocopy (*inode);
340 root.add_child_nocopy (*freeze_node);
343 /* Alignment: act as a proxy for the diskstream */
345 XMLNode* align_node = new XMLNode (X_("Alignment"));
346 AlignStyle as = _diskstream->alignment_style ();
347 align_node->add_property (X_("style"), enum_2_string (as));
348 root.add_child_nocopy (*align_node);
350 root.add_property (X_("mode"), enum_2_string (_mode));
352 /* we don't return diskstream state because we don't
353 own the diskstream exclusively. control of the diskstream
354 state is ceded to the Session, even if we create the
358 _diskstream->id().print (buf, sizeof (buf));
359 root.add_property ("diskstream-id", buf);
361 root.add_child_nocopy (_rec_enable_control->get_state());
367 AudioTrack::set_state_part_two ()
371 LocaleGuard lg (X_("POSIX"));
373 /* This is called after all session state has been restored but before
374 have been made ports and connections are established.
377 if (pending_state == 0) {
381 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
383 _freeze_record.state = Frozen;
385 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
388 _freeze_record.processor_info.clear ();
390 if ((prop = fnode->property (X_("playlist"))) != 0) {
391 boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value());
393 _freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
395 _freeze_record.playlist.reset ();
396 _freeze_record.state = NoFreeze;
401 if ((prop = fnode->property (X_("state"))) != 0) {
402 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
405 XMLNodeConstIterator citer;
406 XMLNodeList clist = fnode->children();
408 for (citer = clist.begin(); citer != clist.end(); ++citer) {
409 if ((*citer)->name() != X_("processor")) {
413 if ((prop = (*citer)->property (X_("id"))) == 0) {
417 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
418 boost::shared_ptr<Processor>());
419 frii->id = prop->value ();
420 _freeze_record.processor_info.push_back (frii);
424 /* Alignment: act as a proxy for the diskstream */
426 if ((fnode = find_named_node (*pending_state, X_("Alignment"))) != 0) {
428 if ((prop = fnode->property (X_("style"))) != 0) {
430 /* fix for older sessions from before EnumWriter */
434 if (prop->value() == "capture") {
435 pstr = "CaptureTime";
436 } else if (prop->value() == "existing") {
437 pstr = "ExistingMaterial";
439 pstr = prop->value();
442 AlignStyle as = AlignStyle (string_2_enum (pstr, as));
443 _diskstream->set_persistent_align_style (as);
450 AudioTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
451 bool session_state_changing, bool can_record, bool rec_monitors_input)
453 if (n_outputs().n_total() == 0) {
458 silence (nframes, offset);
462 if (session_state_changing) {
464 /* XXX is this safe to do against transport state changes? */
466 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
470 audio_diskstream()->check_record_status (start_frame, nframes, can_record);
474 if (_have_internal_generator) {
475 /* since the instrument has no input streams,
476 there is no reason to send any signal
482 if (!Config->get_tape_machine_mode()) {
484 ADATs work in a strange way..
485 they monitor input always when stopped.and auto-input is engaged.
487 if ((Config->get_monitoring_model() == SoftwareMonitoring) && (Config->get_auto_input () || _diskstream->record_enabled())) {
488 send_silence = false;
494 Other machines switch to input on stop if the track is record enabled,
495 regardless of the auto input setting (auto input only changes the
496 monitoring state when the transport is rolling)
498 if ((Config->get_monitoring_model() == SoftwareMonitoring) && _diskstream->record_enabled()) {
499 send_silence = false;
506 apply_gain_automation = false;
510 /* if we're sending silence, but we want the meters to show levels for the signal,
514 if (_have_internal_generator) {
515 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
517 if (_meter_point == MeterInput) {
518 just_meter_input (start_frame, end_frame, nframes, offset);
520 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
525 /* we're sending signal, but we may still want to meter the input.
528 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
535 AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick,
536 bool can_record, bool rec_monitors_input)
541 nframes_t transport_frame;
542 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
545 Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
547 // automation snapshot can also be called from the non-rt context
548 // and it uses the redirect list, so we take the lock out here
549 automation_snapshot (start_frame, false);
554 if (n_outputs().n_total() == 0 && _processors.empty()) {
559 silence (nframes, offset);
563 transport_frame = _session.transport_frame();
565 prepare_inputs( nframes, offset );
567 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
568 /* need to do this so that the diskstream sets its
569 playback distance to zero, thus causing diskstream::commit
572 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
576 apply_gain_automation = false;
578 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
580 silence (nframes, offset);
585 /* special condition applies */
587 if (_meter_point == MeterInput) {
588 just_meter_input (start_frame, end_frame, nframes, offset);
591 if (diskstream->record_enabled() && !can_record && !Config->get_auto_input()) {
593 /* not actually recording, but we want to hear the input material anyway,
594 at least potentially (depending on monitoring options)
597 passthru (start_frame, end_frame, nframes, offset, 0, true);
599 } else if ((b = diskstream->playback_buffer(0)) != 0) {
602 XXX is it true that the earlier test on n_outputs()
603 means that we can avoid checking it again here? i think
604 so, because changing the i/o configuration of an IO
605 requires holding the AudioEngine lock, which we hold
606 while in the process() tree.
610 /* copy the diskstream data to all output buffers */
612 size_t limit = n_process_buffers().n_audio();
613 BufferSet& bufs = _session.get_scratch_buffers ();
614 const size_t blimit = bufs.count().n_audio();
619 if (limit > blimit) {
621 /* example case: auditioner configured for stereo output,
622 but loaded with an 8 channel file. there are only
623 2 passthrough buffers, but n_process_buffers() will
626 arbitrary decision: map all channels in the diskstream
627 to the outputs available.
630 float scaling = limit/blimit;
632 for (i = 0, n = 1; i < blimit; ++i, ++n) {
634 /* first time through just copy a channel into
638 Sample* bb = bufs.get_audio (i).data();
640 for (nframes_t xx = 0; xx < nframes; ++xx) {
641 bb[xx] = b[xx] * scaling;
644 if (n < diskstream->n_channels().n_audio()) {
645 tmpb = diskstream->playback_buffer(n);
652 for (;i < limit; ++i, ++n) {
654 /* for all remaining channels, sum with existing
655 data in the output buffers
658 bufs.get_audio (i%blimit).accumulate_with_gain_from (b, nframes, 0, scaling);
660 if (n < diskstream->n_channels().n_audio()) {
661 tmpb = diskstream->playback_buffer(n);
672 for (i = 0, n = 1; i < blimit; ++i, ++n) {
673 memcpy (bufs.get_audio (i).data(), b, sizeof (Sample) * nframes);
674 if (n < diskstream->n_channels().n_audio()) {
675 tmpb = diskstream->playback_buffer(n);
683 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
685 if (!diskstream->record_enabled() && _session.transport_rolling()) {
686 Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
688 if (am.locked() && gain_control()->automation_playback()) {
689 apply_gain_automation = gain_control()->list()->curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
693 process_output_buffers (bufs, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
696 /* problem with the diskstream; just be quiet for a bit */
697 silence (nframes, offset);
704 AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
705 bool can_record, bool rec_monitors_input)
707 if (n_outputs().n_total() == 0 && _processors.empty()) {
712 silence (nframes, offset);
717 apply_gain_automation = false;
719 silence (nframes, offset);
721 return audio_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
725 AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes, bool enable_processing)
727 gain_t gain_automation[nframes];
728 gain_t gain_buffer[nframes];
729 float mix_buffer[nframes];
730 ProcessorList::iterator i;
731 bool post_fader_work = false;
732 gain_t this_gain = _gain;
733 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
735 Glib::RWLock::ReaderLock rlock (_processor_lock);
737 boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
740 assert(buffers.get_audio(0).capacity() >= nframes);
742 if (apl->read (buffers.get_audio(0).data(), mix_buffer, gain_buffer, start, nframes) != nframes) {
746 assert(buffers.count().n_audio() >= 1);
748 Sample* b = buffers.get_audio(0).data();
749 BufferSet::audio_iterator bi = buffers.audio_begin();
751 for ( ; bi != buffers.audio_end(); ++bi, ++n) {
752 if (n < diskstream->n_channels().n_audio()) {
753 if (apl->read (bi->data(), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
759 /* duplicate last across remaining buffers */
760 memcpy (bi->data(), b, sizeof (Sample) * nframes);
764 // If no processing is required, there's no need to go any further.
765 if (!enable_processing)
768 /* note: only run processors during export. other layers in the machinery
769 will already have checked that there are no external port processors.
772 for (i = _processors.begin(); i != _processors.end(); ++i) {
773 boost::shared_ptr<Processor> processor;
775 if ((processor = boost::dynamic_pointer_cast<Processor>(*i)) != 0) {
776 switch (processor->placement()) {
778 processor->run_in_place (buffers, start, start+nframes, nframes, 0);
781 post_fader_work = true;
787 if (gain_control()->automation_state() == Play) {
789 gain_control()->list()->curve().get_vector (start, start + nframes, gain_automation, nframes);
791 for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
792 Sample *b = bi->data();
793 for (nframes_t n = 0; n < nframes; ++n) {
794 b[n] *= gain_automation[n];
800 for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
801 Sample *b = bi->data();
802 for (nframes_t n = 0; n < nframes; ++n) {
808 if (post_fader_work) {
810 for (i = _processors.begin(); i != _processors.end(); ++i) {
811 boost::shared_ptr<PluginInsert> processor;
813 if ((processor = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
814 switch ((*i)->placement()) {
818 processor->run_in_place (buffers, start, start+nframes, nframes, 0);
828 boost::shared_ptr<Region>
829 AudioTrack::bounce (InterThreadInfo& itt)
831 vector<boost::shared_ptr<Source> > srcs;
832 return _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), false, srcs, itt);
835 boost::shared_ptr<Region>
836 AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt, bool enable_processing)
838 vector<boost::shared_ptr<Source> > srcs;
839 return _session.write_one_track (*this, start, end, false, srcs, itt, enable_processing);
843 AudioTrack::freeze (InterThreadInfo& itt)
845 vector<boost::shared_ptr<Source> > srcs;
846 string new_playlist_name;
847 boost::shared_ptr<Playlist> new_playlist;
850 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
852 if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) {
858 while (n < (UINT_MAX-1)) {
862 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
864 if (_session.playlist_by_name (candidate) == 0) {
865 new_playlist_name = candidate;
873 if (n == (UINT_MAX-1)) {
874 error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
875 " to create another one"), _freeze_record.playlist->name())
880 boost::shared_ptr<Region> res;
882 if ((res = _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) {
886 _freeze_record.processor_info.clear ();
889 Glib::RWLock::ReaderLock lm (_processor_lock);
891 for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); ++r) {
893 boost::shared_ptr<Processor> processor;
895 if ((processor = boost::dynamic_pointer_cast<Processor>(*r)) != 0) {
897 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo ((*r)->get_state(), processor);
899 frii->id = processor->id();
901 _freeze_record.processor_info.push_back (frii);
903 /* now deactivate the processor */
905 processor->deactivate ();
906 _session.set_dirty ();
911 new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
913 _freeze_record.gain = _gain;
914 _freeze_record.gain_automation_state = _gain_control->automation_state();
915 _freeze_record.pan_automation_state = _panner->automation_state();
917 region_name = new_playlist_name;
919 /* create a new region from all filesources, keep it private */
921 boost::shared_ptr<Region> region (RegionFactory::create (srcs, 0,
922 srcs[0]->length(srcs[0]->timeline_position()),
924 (Region::Flag) (Region::WholeFile|Region::DefaultFlags),
927 new_playlist->set_orig_diskstream_id (diskstream->id());
928 new_playlist->add_region (region, _session.current_start_frame());
929 new_playlist->set_frozen (true);
930 region->set_locked (true);
932 diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
933 diskstream->set_record_enabled (false);
935 /* reset stuff that has already been accounted for in the freeze process */
937 set_gain (1.0, this);
938 _gain_control->set_automation_state (Off);
939 _panner->set_automation_state (Off);
941 _freeze_record.state = Frozen;
942 FreezeChange(); /* EMIT SIGNAL */
946 AudioTrack::unfreeze ()
948 if (_freeze_record.playlist) {
949 audio_diskstream()->use_playlist (_freeze_record.playlist);
952 Glib::RWLock::ReaderLock lm (_processor_lock); // should this be a write lock? jlc
953 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
954 for (vector<FreezeRecordProcessorInfo*>::iterator ii = _freeze_record.processor_info.begin(); ii != _freeze_record.processor_info.end(); ++ii) {
955 if ((*ii)->id == (*i)->id()) {
956 (*i)->set_state (((*ii)->state));
963 _freeze_record.playlist.reset ();
964 set_gain (_freeze_record.gain, this);
965 _gain_control->set_automation_state (_freeze_record.gain_automation_state);
966 _panner->set_automation_state (_freeze_record.pan_automation_state);
969 _freeze_record.state = UnFrozen;
970 FreezeChange (); /* EMIT SIGNAL */