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, int declick, bool meter)
468 uint32_t nbufs = n_process_buffers ();
470 process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, true, declick, meter);
474 AudioTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
475 bool session_state_changing, bool can_record, bool rec_monitors_input)
477 if (n_outputs() == 0) {
486 if (session_state_changing) {
488 /* XXX is this safe to do against transport state changes? */
490 passthru_silence (start_frame, end_frame, nframes, 0, false);
494 audio_diskstream()->check_record_status (start_frame, nframes, can_record);
498 if (_have_internal_generator) {
499 /* since the instrument has no input streams,
500 there is no reason to send any signal
506 if (!Config->get_tape_machine_mode()) {
508 ADATs work in a strange way..
509 they monitor input always when stopped.and auto-input is engaged.
511 if ((Config->get_monitoring_model() == SoftwareMonitoring) && (Config->get_auto_input () || _diskstream->record_enabled())) {
512 send_silence = false;
518 Other machines switch to input on stop if the track is record enabled,
519 regardless of the auto input setting (auto input only changes the
520 monitoring state when the transport is rolling)
522 if ((Config->get_monitoring_model() == SoftwareMonitoring) && _diskstream->record_enabled()) {
523 send_silence = false;
530 apply_gain_automation = false;
534 /* if we're sending silence, but we want the meters to show levels for the signal,
538 if (_have_internal_generator) {
539 passthru_silence (start_frame, end_frame, nframes, 0, true);
541 if (_meter_point == MeterInput) {
542 just_meter_input (start_frame, end_frame, nframes);
544 passthru_silence (start_frame, end_frame, nframes, 0, false);
549 /* we're sending signal, but we may still want to meter the input.
552 passthru (start_frame, end_frame, nframes, 0, (_meter_point == MeterInput));
559 AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int declick,
560 bool can_record, bool rec_monitors_input)
565 nframes_t transport_frame;
566 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
569 Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
571 // automation snapshot can also be called from the non-rt context
572 // and it uses the redirect list, so we take the lock out here
573 automation_snapshot (start_frame, false);
578 if (n_outputs() == 0 && _redirects.empty()) {
587 transport_frame = _session.transport_frame();
589 if (!can_record || !diskstream->record_enabled()) {
590 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
591 /* need to do this so that the diskstream sets its
592 playback distance to zero, thus causing diskstream::commit
595 return diskstream->process (transport_frame, 0, can_record, rec_monitors_input);
600 apply_gain_automation = false;
602 if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input)) != 0) {
609 /* special condition applies */
611 if (_meter_point == MeterInput) {
612 just_meter_input (start_frame, end_frame, nframes);
615 if (diskstream->record_enabled() && !can_record && !Config->get_auto_input()) {
617 /* not actually recording, but we want to hear the input material anyway,
618 at least potentially (depending on monitoring options)
621 passthru (start_frame, end_frame, nframes, 0, true);
623 } else if ((b = diskstream->playback_buffer(0)) != 0) {
626 XXX is it true that the earlier test on n_outputs()
627 means that we can avoid checking it again here? i think
628 so, because changing the i/o configuration of an IO
629 requires holding the AudioEngine lock, which we hold
630 while in the process() tree.
634 /* copy the diskstream data to all output buffers */
636 vector<Sample*>& bufs = _session.get_passthru_buffers ();
637 vector<Sample*>::size_type blimit = bufs.size();
638 uint32_t limit = n_process_buffers ();
643 if (limit > blimit) {
645 /* example case: auditioner configured for stereo output,
646 but loaded with an 8 channel file. there are only
647 2 passthrough buffers, but n_process_buffers() will
650 arbitrary decision: map all channels in the diskstream
651 to the outputs available.
654 float scaling = limit/blimit;
656 for (i = 0, n = 1; i < blimit; ++i, ++n) {
658 /* first time through just copy a channel into
662 for (nframes_t xx = 0; xx < nframes; ++xx) {
663 bufs[i][xx] = b[xx] * scaling;
666 if (n < diskstream->n_channels()) {
667 tmpb = diskstream->playback_buffer(n);
674 for (;i < limit; ++i, ++n) {
676 /* for all remaining channels, sum with existing
677 data in the output buffers
680 Session::mix_buffers_with_gain (bufs[i%blimit], b, nframes, scaling);
682 if (n < diskstream->n_channels()) {
683 tmpb = diskstream->playback_buffer(n);
694 for (i = 0, n = 1; i < limit; ++i, ++n) {
695 memcpy (bufs[i], b, sizeof (Sample) * nframes);
696 if (n < diskstream->n_channels()) {
697 tmpb = diskstream->playback_buffer(n);
705 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
707 if (!diskstream->record_enabled() && _session.transport_rolling()) {
708 Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
710 if (am.locked() && gain_automation_playback()) {
711 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
715 process_output_buffers (bufs, limit, start_frame, end_frame, nframes, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
718 /* problem with the diskstream; just be quiet for a bit */
726 AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
727 bool can_record, bool rec_monitors_input)
729 if (n_outputs() == 0 && _redirects.empty()) {
739 apply_gain_automation = false;
743 return audio_diskstream()->process (_session.transport_frame(), nframes, can_record, rec_monitors_input);
747 AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, nframes_t start, nframes_t nframes, bool enable_processing)
749 gain_t gain_automation[nframes];
750 gain_t gain_buffer[nframes];
751 float mix_buffer[nframes];
752 RedirectList::iterator i;
753 bool post_fader_work = false;
754 gain_t this_gain = _gain;
755 vector<Sample*>::iterator bi;
757 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
759 Glib::RWLock::ReaderLock rlock (redirect_lock);
761 boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
764 if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
769 bi = buffers.begin();
772 for (; bi != buffers.end(); ++bi, ++n) {
773 if (n < diskstream->n_channels()) {
774 if (apl->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
780 /* duplicate last across remaining buffers */
781 memcpy ((*bi), b, sizeof (Sample) * nframes);
785 // If no processing is required, there's no need to go any further.
786 if (!enable_processing)
789 /* note: only run inserts during export. other layers in the machinery
790 will already have checked that there are no external port inserts.
793 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
794 boost::shared_ptr<Insert> insert;
796 if ((insert = boost::dynamic_pointer_cast<Insert>(*i)) != 0) {
797 switch (insert->placement()) {
799 insert->run (buffers, nbufs, nframes);
802 post_fader_work = true;
808 if (_gain_automation_curve.automation_state() == Play) {
810 _gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
812 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
814 for (nframes_t n = 0; n < nframes; ++n) {
815 b[n] *= gain_automation[n];
821 for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
822 apply_gain_to_buffer(*bi, nframes, this_gain);
826 if (post_fader_work) {
828 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
829 boost::shared_ptr<PluginInsert> insert;
831 if ((insert = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
832 switch ((*i)->placement()) {
836 insert->run (buffers, nbufs, nframes);
846 boost::shared_ptr<Region>
847 AudioTrack::bounce (InterThreadInfo& itt)
849 vector<boost::shared_ptr<AudioSource> > srcs;
850 return _session.write_one_audio_track (*this, _session.current_start_frame(), _session.current_end_frame(),
855 boost::shared_ptr<Region>
856 AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt, bool enable_processing)
858 vector<boost::shared_ptr<AudioSource> > srcs;
859 return _session.write_one_audio_track (*this, start, end, false, srcs, itt, enable_processing);
863 AudioTrack::freeze (InterThreadInfo& itt)
865 vector<boost::shared_ptr<AudioSource> > srcs;
866 string new_playlist_name;
867 boost::shared_ptr<Playlist> new_playlist;
870 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
872 if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) {
878 while (n < (UINT_MAX-1)) {
882 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
884 if (_session.playlist_by_name (candidate) == 0) {
885 new_playlist_name = candidate;
893 if (n == (UINT_MAX-1)) {
894 error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
895 " to create another one"), _freeze_record.playlist->name())
900 boost::shared_ptr<Region> res;
902 if ((res = _session.write_one_audio_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) {
906 _freeze_record.insert_info.clear ();
907 _freeze_record.have_mementos = true;
910 Glib::RWLock::ReaderLock lm (redirect_lock);
912 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
914 boost::shared_ptr<Insert> insert;
916 if ((insert = boost::dynamic_pointer_cast<Insert>(*r)) != 0) {
918 FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo ((*r)->get_state(), insert);
920 frii->id = insert->id();
922 _freeze_record.insert_info.push_back (frii);
924 /* now deactivate the insert */
926 insert->set_active (false, this);
931 _freeze_record.gain = _gain;
932 _freeze_record.gain_automation_state = _gain_automation_curve.automation_state();
933 _freeze_record.pan_automation_state = _panner->automation_state();
935 new_playlist = PlaylistFactory::create (_session, new_playlist_name, false);
936 region_name = new_playlist_name;
938 /* create a new region from all filesources, keep it private */
940 boost::shared_ptr<Region> region (RegionFactory::create (srcs, 0, srcs[0]->length(),
942 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
945 new_playlist->set_orig_diskstream_id (diskstream->id());
946 new_playlist->add_region (region, _session.current_start_frame());
947 new_playlist->set_frozen (true);
948 region->set_locked (true);
950 diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
951 diskstream->set_record_enabled (false);
953 /* reset stuff that has already been accounted for in the freeze process */
955 set_gain (1.0, this);
956 _gain_automation_curve.set_automation_state (Off);
957 _panner->set_automation_state (Off);
959 _freeze_record.state = Frozen;
960 FreezeChange(); /* EMIT SIGNAL */
964 AudioTrack::unfreeze ()
966 if (_freeze_record.playlist) {
967 audio_diskstream()->use_playlist (_freeze_record.playlist);
969 if (_freeze_record.have_mementos) {
971 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
977 Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
978 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
979 for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
980 if ((*ii)->id == (*i)->id()) {
981 (*i)->set_state (((*ii)->state));
988 _freeze_record.playlist.reset ();
989 set_gain (_freeze_record.gain, this);
990 _gain_automation_curve.set_automation_state (_freeze_record.gain_automation_state);
991 _panner->set_automation_state (_freeze_record.pan_automation_state);
994 _freeze_record.state = UnFrozen;
995 FreezeChange (); /* EMIT SIGNAL */