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/redirect.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/insert.h>
36 #include <ardour/audioplaylist.h>
37 #include <ardour/playlist_factory.h>
38 #include <ardour/panner.h>
39 #include <ardour/utils.h>
40 #include <ardour/mix.h>
45 using namespace ARDOUR;
48 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
49 : Track (sess, name, flag, mode)
51 use_new_diskstream ();
54 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
57 _set_state (node, false);
60 AudioTrack::~AudioTrack ()
65 AudioTrack::use_new_diskstream ()
67 AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
69 if (_flags & Hidden) {
70 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Hidden);
72 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Recordable);
75 if (_mode == Destructive) {
76 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
79 boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name(), dflags));
81 _session.add_diskstream (ds);
83 set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
87 AudioTrack::set_mode (TrackMode m)
91 if (_diskstream->set_destructive (m == Destructive)) {
97 TrackModeChanged (); /* EMIT SIGNAL */
104 AudioTrack::can_use_mode (TrackMode m, bool& bounce_required)
108 bounce_required = false;
113 return _diskstream->can_become_destructive (bounce_required);
118 AudioTrack::deprecated_use_diskstream_connections ()
120 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
122 if (diskstream->deprecated_io_node == 0) {
126 const XMLProperty* prop;
127 XMLNode& node (*diskstream->deprecated_io_node);
129 /* don't do this more than once. */
131 diskstream->deprecated_io_node = 0;
133 set_input_minimum (-1);
134 set_input_maximum (-1);
135 set_output_minimum (-1);
136 set_output_maximum (-1);
138 if ((prop = node.property ("gain")) != 0) {
139 set_gain (atof (prop->value().c_str()), this);
140 _gain = _desired_gain;
143 if ((prop = node.property ("input-connection")) != 0) {
144 Connection* c = _session.connection_by_name (prop->value());
147 error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
149 string replacement_connection;
151 if (prop->value().find ('+') != string::npos) {
152 replacement_connection = _("in 1+2");
154 replacement_connection = _("in 1");
157 if ((c = _session.connection_by_name (replacement_connection)) == 0) {
158 error << _("No input connections available as a replacement")
162 info << string_compose (_("Connection %1 was not available - \"%2\" used instead"), prop->value(), replacement_connection)
167 use_input_connection (*c, this);
169 } else if ((prop = node.property ("inputs")) != 0) {
170 if (set_inputs (prop->value())) {
171 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
180 AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
183 _diskstream->set_io (*this);
184 _diskstream->set_destructive (_mode == Destructive);
186 if (audio_diskstream()->deprecated_io_node) {
188 if (!connecting_legal) {
189 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
191 deprecated_use_diskstream_connections ();
195 _diskstream->set_record_enabled (false);
196 _diskstream->monitor_input (false);
198 ic_connection.disconnect();
199 ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
201 DiskstreamChanged (); /* EMIT SIGNAL */
207 AudioTrack::use_diskstream (string name)
209 boost::shared_ptr<AudioDiskstream> dstream;
211 if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream>(_session.diskstream_by_name (name))) == 0) {
212 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
216 return set_diskstream (dstream, this);
220 AudioTrack::use_diskstream (const PBD::ID& id)
222 boost::shared_ptr<AudioDiskstream> dstream;
224 if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream> (_session.diskstream_by_id (id))) == 0) {
225 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
229 return set_diskstream (dstream, this);
232 boost::shared_ptr<AudioDiskstream>
233 AudioTrack::audio_diskstream() const
235 return boost::dynamic_pointer_cast<AudioDiskstream>(_diskstream);
239 AudioTrack::set_state (const XMLNode& node)
241 return _set_state (node, true);
245 AudioTrack::_set_state (const XMLNode& node, bool call_base)
247 const XMLProperty *prop;
248 XMLNodeConstIterator iter;
251 if (Route::_set_state (node, call_base)) {
256 if ((prop = node.property (X_("mode"))) != 0) {
257 _mode = TrackMode (string_2_enum (prop->value(), _mode));
262 if ((prop = node.property ("diskstream-id")) == 0) {
264 /* some old sessions use the diskstream name rather than the ID */
266 if ((prop = node.property ("diskstream")) == 0) {
267 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
272 if (use_diskstream (prop->value())) {
278 PBD::ID id (prop->value());
281 /* this wierd hack is used when creating tracks from a template. there isn't
282 a particularly good time to interpose between setting the first part of
283 the track state (notably Route::set_state() and the track mode), and the
284 second part (diskstream stuff). So, we have a special ID for the diskstream
285 that means "you should create a new diskstream here, not look for
290 use_new_diskstream ();
291 } else if (use_diskstream (id)) {
298 XMLNodeConstIterator niter;
301 nlist = node.children();
302 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
305 if (child->name() == X_("recenable")) {
306 _rec_enable_control.set_state (*child);
307 _session.add_controllable (&_rec_enable_control);
311 pending_state = const_cast<XMLNode*> (&node);
313 if (_session.state_of_the_state() & Session::Loading) {
314 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
316 set_state_part_two ();
323 AudioTrack::state(bool full_state)
325 XMLNode& root (Route::state(full_state));
326 XMLNode* freeze_node;
329 if (_freeze_record.playlist) {
332 freeze_node = new XMLNode (X_("freeze-info"));
333 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
334 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
336 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
337 inode = new XMLNode (X_("insert"));
338 (*i)->id.print (buf, sizeof (buf));
339 inode->add_property (X_("id"), buf);
340 inode->add_child_copy ((*i)->state);
342 freeze_node->add_child_nocopy (*inode);
345 root.add_child_nocopy (*freeze_node);
348 /* Alignment: act as a proxy for the diskstream */
350 XMLNode* align_node = new XMLNode (X_("alignment"));
351 AlignStyle as = _diskstream->alignment_style ();
352 align_node->add_property (X_("style"), enum_2_string (as));
353 root.add_child_nocopy (*align_node);
355 root.add_property (X_("mode"), enum_2_string (_mode));
357 /* we don't return diskstream state because we don't
358 own the diskstream exclusively. control of the diskstream
359 state is ceded to the Session, even if we create the
363 _diskstream->id().print (buf, sizeof (buf));
364 root.add_property ("diskstream-id", buf);
366 root.add_child_nocopy (_rec_enable_control.get_state());
372 AudioTrack::set_state_part_two ()
376 LocaleGuard lg (X_("POSIX"));
378 /* During session loading: this is called after all session state has been restored but before
379 ports have been created and connections are established.
381 During creation from templates: this is called after ports have been created, and connections
385 if (pending_state == 0) {
389 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
392 _freeze_record.have_mementos = false;
393 _freeze_record.state = Frozen;
395 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
398 _freeze_record.insert_info.clear ();
400 if ((prop = fnode->property (X_("playlist"))) != 0) {
401 boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value());
403 _freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
405 _freeze_record.playlist.reset ();
406 _freeze_record.state = NoFreeze;
411 if ((prop = fnode->property (X_("state"))) != 0) {
412 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
415 XMLNodeConstIterator citer;
416 XMLNodeList clist = fnode->children();
418 for (citer = clist.begin(); citer != clist.end(); ++citer) {
419 if ((*citer)->name() != X_("insert")) {
423 if ((prop = (*citer)->property (X_("id"))) == 0) {
427 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()),
428 boost::shared_ptr<Insert>());
429 frii->id = prop->value ();
430 _freeze_record.insert_info.push_back (frii);
434 /* Alignment: act as a proxy for the diskstream */
436 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
438 if ((prop = fnode->property (X_("style"))) != 0) {
440 /* fix for older sessions from before EnumWriter */
444 if (prop->value() == "capture") {
445 pstr = "CaptureTime";
446 } else if (prop->value() == "existing") {
447 pstr = "ExistingMaterial";
449 pstr = prop->value();
452 AlignStyle as = AlignStyle (string_2_enum (pstr, as));
453 _diskstream->set_persistent_align_style (as);
460 AudioTrack::n_process_buffers ()
462 return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
466 AudioTrack::passthru_silence (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset, int declick, bool meter)
468 uint32_t nbufs = n_process_buffers ();
469 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
473 AudioTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
474 bool session_state_changing, bool can_record, bool rec_monitors_input)
476 if (n_outputs() == 0) {
481 silence (nframes, offset);
485 if (session_state_changing) {
487 /* XXX is this safe to do against transport state changes? */
489 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
493 audio_diskstream()->check_record_status (start_frame, nframes, can_record);
497 if (_have_internal_generator) {
498 /* since the instrument has no input streams,
499 there is no reason to send any signal
505 if (!Config->get_tape_machine_mode()) {
507 ADATs work in a strange way..
508 they monitor input always when stopped.and auto-input is engaged.
510 if ((Config->get_monitoring_model() == SoftwareMonitoring) && (Config->get_auto_input () || _diskstream->record_enabled())) {
511 send_silence = false;
517 Other machines switch to input on stop if the track is record enabled,
518 regardless of the auto input setting (auto input only changes the
519 monitoring state when the transport is rolling)
521 if ((Config->get_monitoring_model() == SoftwareMonitoring) && _diskstream->record_enabled()) {
522 send_silence = false;
529 apply_gain_automation = false;
533 /* if we're sending silence, but we want the meters to show levels for the signal,
537 if (_have_internal_generator) {
538 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
540 if (_meter_point == MeterInput) {
541 just_meter_input (start_frame, end_frame, nframes, offset);
543 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
548 /* we're sending signal, but we may still want to meter the input.
551 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
558 AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick,
559 bool can_record, bool rec_monitors_input)
564 nframes_t transport_frame;
565 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
568 Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
570 // automation snapshot can also be called from the non-rt context
571 // and it uses the redirect list, so we take the lock out here
572 automation_snapshot (start_frame, false);
577 if (n_outputs() == 0 && _redirects.empty()) {
582 silence (nframes, offset);
586 transport_frame = _session.transport_frame();
588 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
589 /* need to do this so that the diskstream sets its
590 playback distance to zero, thus causing diskstream::commit
593 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
597 apply_gain_automation = false;
599 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
601 silence (nframes, offset);
606 /* special condition applies */
608 if (_meter_point == MeterInput) {
609 just_meter_input (start_frame, end_frame, nframes, offset);
612 if (diskstream->record_enabled() && !can_record && !Config->get_auto_input()) {
614 /* not actually recording, but we want to hear the input material anyway,
615 at least potentially (depending on monitoring options)
618 passthru (start_frame, end_frame, nframes, offset, 0, true);
620 } else if ((b = diskstream->playback_buffer(0)) != 0) {
623 XXX is it true that the earlier test on n_outputs()
624 means that we can avoid checking it again here? i think
625 so, because changing the i/o configuration of an IO
626 requires holding the AudioEngine lock, which we hold
627 while in the process() tree.
631 /* copy the diskstream data to all output buffers */
633 vector<Sample*>& bufs = _session.get_passthru_buffers ();
634 vector<Sample*>::size_type blimit = bufs.size();
635 uint32_t limit = n_process_buffers ();
640 if (limit > blimit) {
642 /* example case: auditioner configured for stereo output,
643 but loaded with an 8 channel file. there are only
644 2 passthrough buffers, but n_process_buffers() will
647 arbitrary decision: map all channels in the diskstream
648 to the outputs available.
651 float scaling = limit/blimit;
653 for (i = 0, n = 1; i < blimit; ++i, ++n) {
655 /* first time through just copy a channel into
659 for (nframes_t xx = 0; xx < nframes; ++xx) {
660 bufs[i][xx] = b[xx] * scaling;
663 if (n < diskstream->n_channels()) {
664 tmpb = diskstream->playback_buffer(n);
671 for (;i < limit; ++i, ++n) {
673 /* for all remaining channels, sum with existing
674 data in the output buffers
677 Session::mix_buffers_with_gain (bufs[i%blimit], b, nframes, scaling);
679 if (n < diskstream->n_channels()) {
680 tmpb = diskstream->playback_buffer(n);
691 for (i = 0, n = 1; i < limit; ++i, ++n) {
692 memcpy (bufs[i], b, sizeof (Sample) * nframes);
693 if (n < diskstream->n_channels()) {
694 tmpb = diskstream->playback_buffer(n);
702 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
704 if (!diskstream->record_enabled() && _session.transport_rolling()) {
705 Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
707 if (am.locked() && gain_automation_playback()) {
708 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
712 process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
715 /* problem with the diskstream; just be quiet for a bit */
716 silence (nframes, offset);
723 AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
724 bool can_record, bool rec_monitors_input)
726 if (n_outputs() == 0 && _redirects.empty()) {
731 silence (nframes, offset);
736 apply_gain_automation = false;
738 silence (nframes, offset);
740 return audio_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
744 AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, nframes_t start, nframes_t nframes, bool enable_processing)
746 gain_t gain_automation[nframes];
747 gain_t gain_buffer[nframes];
748 float mix_buffer[nframes];
749 RedirectList::iterator i;
750 bool post_fader_work = false;
751 gain_t this_gain = _gain;
752 vector<Sample*>::iterator bi;
754 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
756 Glib::RWLock::ReaderLock rlock (redirect_lock);
758 boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
761 if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
766 bi = buffers.begin();
769 for (; bi != buffers.end(); ++bi, ++n) {
770 if (n < diskstream->n_channels()) {
771 if (apl->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
777 /* duplicate last across remaining buffers */
778 memcpy ((*bi), b, sizeof (Sample) * nframes);
782 // If no processing is required, there's no need to go any further.
783 if (!enable_processing)
786 /* note: only run inserts during export. other layers in the machinery
787 will already have checked that there are no external port inserts.
790 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
791 boost::shared_ptr<Insert> insert;
793 if ((insert = boost::dynamic_pointer_cast<Insert>(*i)) != 0) {
794 switch (insert->placement()) {
796 insert->run (buffers, nbufs, nframes, 0);
799 post_fader_work = true;
805 if (_gain_automation_curve.automation_state() == Play) {
807 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
809 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
811 for (nframes_t n = 0; n < nframes; ++n) {
812 b[n] *= gain_automation[n];
818 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
819 apply_gain_to_buffer(*bi, nframes, this_gain);
823 if (post_fader_work) {
825 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
826 boost::shared_ptr<PluginInsert> insert;
828 if ((insert = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
829 switch ((*i)->placement()) {
833 insert->run (buffers, nbufs, nframes, 0);
843 boost::shared_ptr<Region>
844 AudioTrack::bounce (InterThreadInfo& itt)
846 vector<boost::shared_ptr<AudioSource> > srcs;
847 return _session.write_one_audio_track (*this, _session.current_start_frame(), _session.current_end_frame(),
852 boost::shared_ptr<Region>
853 AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt, bool enable_processing)
855 vector<boost::shared_ptr<AudioSource> > srcs;
856 return _session.write_one_audio_track (*this, start, end, false, srcs, itt, enable_processing);
860 AudioTrack::freeze (InterThreadInfo& itt)
862 vector<boost::shared_ptr<AudioSource> > srcs;
863 string new_playlist_name;
864 boost::shared_ptr<Playlist> new_playlist;
867 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
869 if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) {
875 while (n < (UINT_MAX-1)) {
879 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
881 if (_session.playlist_by_name (candidate) == 0) {
882 new_playlist_name = candidate;
890 if (n == (UINT_MAX-1)) {
891 error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
892 " to create another one"), _freeze_record.playlist->name())
897 boost::shared_ptr<Region> res;
899 if ((res = _session.write_one_audio_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) {
903 _freeze_record.insert_info.clear ();
904 _freeze_record.have_mementos = true;
907 Glib::RWLock::ReaderLock lm (redirect_lock);
909 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
911 boost::shared_ptr<Insert> insert;
913 if ((insert = boost::dynamic_pointer_cast<Insert>(*r)) != 0) {
915 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state(), insert);
917 frii->id = insert->id();
919 _freeze_record.insert_info.push_back (frii);
921 /* now deactivate the insert */
923 insert->set_active (false, this);
928 _freeze_record.gain = _gain;
929 _freeze_record.gain_automation_state = _gain_automation_curve.automation_state();
930 _freeze_record.pan_automation_state = _panner->automation_state();
932 new_playlist = PlaylistFactory::create (_session, new_playlist_name, false);
933 region_name = new_playlist_name;
935 /* create a new region from all filesources, keep it private */
937 boost::shared_ptr<Region> region (RegionFactory::create (srcs, 0, srcs[0]->length(),
939 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
942 new_playlist->set_orig_diskstream_id (diskstream->id());
943 new_playlist->add_region (region, _session.current_start_frame());
944 new_playlist->set_frozen (true);
945 region->set_locked (true);
947 diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
948 diskstream->set_record_enabled (false);
950 /* reset stuff that has already been accounted for in the freeze process */
952 set_gain (1.0, this);
953 _gain_automation_curve.set_automation_state (Off);
954 _panner->set_automation_state (Off);
956 _freeze_record.state = Frozen;
957 FreezeChange(); /* EMIT SIGNAL */
961 AudioTrack::unfreeze ()
963 if (_freeze_record.playlist) {
964 audio_diskstream()->use_playlist (_freeze_record.playlist);
966 if (_freeze_record.have_mementos) {
968 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
974 Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
975 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
976 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
977 if ((*ii)->id == (*i)->id()) {
978 (*i)->set_state (((*ii)->state));
985 _freeze_record.playlist.reset ();
986 set_gain (_freeze_record.gain, this);
987 _gain_automation_curve.set_automation_state (_freeze_record.gain_automation_state);
988 _panner->set_automation_state (_freeze_record.pan_automation_state);
991 _freeze_record.state = UnFrozen;
992 FreezeChange (); /* EMIT SIGNAL */