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);
80 } else if (_mode == NonLayered){
81 dflags = AudioDiskstream::Flag(dflags | AudioDiskstream::NonLayered);
85 boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name(), dflags));
87 _session.add_diskstream (ds);
89 set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
93 AudioTrack::set_mode (TrackMode m)
97 if (_diskstream->set_destructive (m == Destructive)) {
101 _diskstream->set_non_layered (m == NonLayered);
104 TrackModeChanged (); /* EMIT SIGNAL */
111 AudioTrack::can_use_mode (TrackMode m, bool& bounce_required)
116 bounce_required = false;
121 return _diskstream->can_become_destructive (bounce_required);
126 AudioTrack::deprecated_use_diskstream_connections ()
128 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
130 if (diskstream->deprecated_io_node == 0) {
134 const XMLProperty* prop;
135 XMLNode& node (*diskstream->deprecated_io_node);
137 /* don't do this more than once. */
139 diskstream->deprecated_io_node = 0;
141 set_input_minimum (ChanCount::ZERO);
142 set_input_maximum (ChanCount::INFINITE);
143 set_output_minimum (ChanCount::ZERO);
144 set_output_maximum (ChanCount::INFINITE);
146 if ((prop = node.property ("gain")) != 0) {
147 set_gain (atof (prop->value().c_str()), this);
148 _gain = _desired_gain;
151 if ((prop = node.property ("input-connection")) != 0) {
152 boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
155 error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
157 if ((c = _session.bundle_by_name (_("in 1"))) == 0) {
158 error << _("No input bundles available as a replacement")
162 info << string_compose (_("Bundle %1 was not available - \"in 1\" used instead"), prop->value())
167 connect_input_ports_to_bundle (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);
185 _diskstream->set_non_layered (_mode == NonLayered);
187 if (audio_diskstream()->deprecated_io_node) {
189 if (!connecting_legal) {
190 ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
192 deprecated_use_diskstream_connections ();
196 _diskstream->set_record_enabled (false);
197 _diskstream->monitor_input (false);
199 ic_connection.disconnect();
200 ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
202 DiskstreamChanged (); /* EMIT SIGNAL */
208 AudioTrack::use_diskstream (string name)
210 boost::shared_ptr<AudioDiskstream> dstream;
212 if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream>(_session.diskstream_by_name (name))) == 0) {
213 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
217 return set_diskstream (dstream, this);
221 AudioTrack::use_diskstream (const PBD::ID& id)
223 boost::shared_ptr<AudioDiskstream> dstream;
225 if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream> (_session.diskstream_by_id (id))) == 0) {
226 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
230 return set_diskstream (dstream, this);
233 boost::shared_ptr<AudioDiskstream>
234 AudioTrack::audio_diskstream() const
236 return boost::dynamic_pointer_cast<AudioDiskstream>(_diskstream);
240 AudioTrack::set_state (const XMLNode& node)
242 return _set_state (node, true);
246 AudioTrack::_set_state (const XMLNode& node, bool call_base)
248 const XMLProperty *prop;
249 XMLNodeConstIterator iter;
252 if (Route::_set_state (node, call_base)) {
257 if ((prop = node.property (X_("mode"))) != 0) {
258 _mode = TrackMode (string_2_enum (prop->value(), _mode));
263 if ((prop = node.property ("diskstream-id")) == 0) {
265 /* some old sessions use the diskstream name rather than the ID */
267 if ((prop = node.property ("diskstream")) == 0) {
268 fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
273 if (use_diskstream (prop->value())) {
279 PBD::ID id (prop->value());
282 /* this wierd hack is used when creating tracks from a template. there isn't
283 a particularly good time to interpose between setting the first part of
284 the track state (notably Route::set_state() and the track mode), and the
285 second part (diskstream stuff). So, we have a special ID for the diskstream
286 that means "you should create a new diskstream here, not look for
291 use_new_diskstream ();
292 } else if (use_diskstream (id)) {
299 XMLNodeConstIterator niter;
302 nlist = node.children();
303 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
306 if (child->name() == X_("recenable")) {
307 _rec_enable_control->set_state (*child);
308 _session.add_controllable (_rec_enable_control);
312 pending_state = const_cast<XMLNode*> (&node);
314 if (_session.state_of_the_state() & Session::Loading) {
315 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
317 set_state_part_two ();
324 AudioTrack::state(bool full_state)
326 XMLNode& root (Route::state(full_state));
327 XMLNode* freeze_node;
330 if (_freeze_record.playlist) {
333 freeze_node = new XMLNode (X_("freeze-info"));
334 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
335 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
337 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
338 inode = new XMLNode (X_("processor"));
339 (*i)->id.print (buf, sizeof (buf));
340 inode->add_property (X_("id"), buf);
341 inode->add_child_copy ((*i)->state);
343 freeze_node->add_child_nocopy (*inode);
346 root.add_child_nocopy (*freeze_node);
349 /* Alignment: act as a proxy for the diskstream */
351 XMLNode* align_node = new XMLNode (X_("Alignment"));
352 AlignStyle as = _diskstream->alignment_style ();
353 align_node->add_property (X_("style"), enum_2_string (as));
354 root.add_child_nocopy (*align_node);
356 root.add_property (X_("mode"), enum_2_string (_mode));
358 /* we don't return diskstream state because we don't
359 own the diskstream exclusively. control of the diskstream
360 state is ceded to the Session, even if we create the
364 _diskstream->id().print (buf, sizeof (buf));
365 root.add_property ("diskstream-id", buf);
367 root.add_child_nocopy (_rec_enable_control->get_state());
373 AudioTrack::set_state_part_two ()
377 LocaleGuard lg (X_("POSIX"));
379 /* This is called after all session state has been restored but before
380 have been made ports and connections are established.
383 if (pending_state == 0) {
387 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
389 _freeze_record.state = Frozen;
391 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
394 _freeze_record.processor_info.clear ();
396 if ((prop = fnode->property (X_("playlist"))) != 0) {
397 boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value());
399 _freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
401 _freeze_record.playlist.reset ();
402 _freeze_record.state = NoFreeze;
407 if ((prop = fnode->property (X_("state"))) != 0) {
408 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
411 XMLNodeConstIterator citer;
412 XMLNodeList clist = fnode->children();
414 for (citer = clist.begin(); citer != clist.end(); ++citer) {
415 if ((*citer)->name() != X_("processor")) {
419 if ((prop = (*citer)->property (X_("id"))) == 0) {
423 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
424 boost::shared_ptr<Processor>());
425 frii->id = prop->value ();
426 _freeze_record.processor_info.push_back (frii);
430 /* Alignment: act as a proxy for the diskstream */
432 if ((fnode = find_named_node (*pending_state, X_("Alignment"))) != 0) {
434 if ((prop = fnode->property (X_("style"))) != 0) {
436 /* fix for older sessions from before EnumWriter */
440 if (prop->value() == "capture") {
441 pstr = "CaptureTime";
442 } else if (prop->value() == "existing") {
443 pstr = "ExistingMaterial";
445 pstr = prop->value();
448 AlignStyle as = AlignStyle (string_2_enum (pstr, as));
449 _diskstream->set_persistent_align_style (as);
456 AudioTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
457 bool session_state_changing, bool can_record, bool rec_monitors_input)
459 if (n_outputs().n_total() == 0) {
464 silence (nframes, offset);
468 if (session_state_changing) {
470 /* XXX is this safe to do against transport state changes? */
472 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
476 audio_diskstream()->check_record_status (start_frame, nframes, can_record);
480 if (_have_internal_generator) {
481 /* since the instrument has no input streams,
482 there is no reason to send any signal
488 if (!Config->get_tape_machine_mode()) {
490 ADATs work in a strange way..
491 they monitor input always when stopped.and auto-input is engaged.
493 if ((Config->get_monitoring_model() == SoftwareMonitoring) && (Config->get_auto_input () || _diskstream->record_enabled())) {
494 send_silence = false;
500 Other machines switch to input on stop if the track is record enabled,
501 regardless of the auto input setting (auto input only changes the
502 monitoring state when the transport is rolling)
504 if ((Config->get_monitoring_model() == SoftwareMonitoring) && _diskstream->record_enabled()) {
505 send_silence = false;
512 apply_gain_automation = false;
516 /* if we're sending silence, but we want the meters to show levels for the signal,
520 if (_have_internal_generator) {
521 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
523 if (_meter_point == MeterInput) {
524 just_meter_input (start_frame, end_frame, nframes, offset);
526 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
531 /* we're sending signal, but we may still want to meter the input.
534 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
541 AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick,
542 bool can_record, bool rec_monitors_input)
547 nframes_t transport_frame;
548 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
551 Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
553 // automation snapshot can also be called from the non-rt context
554 // and it uses the redirect list, so we take the lock out here
555 automation_snapshot (start_frame, false);
560 if (n_outputs().n_total() == 0 && _processors.empty()) {
565 silence (nframes, offset);
569 transport_frame = _session.transport_frame();
571 prepare_inputs( nframes, offset );
573 if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
574 /* need to do this so that the diskstream sets its
575 playback distance to zero, thus causing diskstream::commit
578 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
582 apply_gain_automation = false;
584 if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
586 silence (nframes, offset);
591 /* special condition applies */
593 if (_meter_point == MeterInput) {
594 just_meter_input (start_frame, end_frame, nframes, offset);
597 if (diskstream->record_enabled() && !can_record && !Config->get_auto_input()) {
599 /* not actually recording, but we want to hear the input material anyway,
600 at least potentially (depending on monitoring options)
603 passthru (start_frame, end_frame, nframes, offset, 0, true);
605 } else if ((b = diskstream->playback_buffer(0)) != 0) {
608 XXX is it true that the earlier test on n_outputs()
609 means that we can avoid checking it again here? i think
610 so, because changing the i/o configuration of an IO
611 requires holding the AudioEngine lock, which we hold
612 while in the process() tree.
616 /* copy the diskstream data to all output buffers */
618 size_t limit = n_process_buffers().n_audio();
619 BufferSet& bufs = _session.get_scratch_buffers ();
620 const size_t blimit = bufs.count().n_audio();
625 if (limit > blimit) {
627 /* example case: auditioner configured for stereo output,
628 but loaded with an 8 channel file. there are only
629 2 passthrough buffers, but n_process_buffers() will
632 arbitrary decision: map all channels in the diskstream
633 to the outputs available.
636 float scaling = limit/blimit;
638 for (i = 0, n = 1; i < blimit; ++i, ++n) {
640 /* first time through just copy a channel into
644 Sample* bb = bufs.get_audio (i).data();
646 for (nframes_t xx = 0; xx < nframes; ++xx) {
647 bb[xx] = b[xx] * scaling;
650 if (n < diskstream->n_channels().n_audio()) {
651 tmpb = diskstream->playback_buffer(n);
658 for (;i < limit; ++i, ++n) {
660 /* for all remaining channels, sum with existing
661 data in the output buffers
664 bufs.get_audio (i%blimit).accumulate_with_gain_from (b, nframes, 0, scaling);
666 if (n < diskstream->n_channels().n_audio()) {
667 tmpb = diskstream->playback_buffer(n);
678 for (i = 0, n = 1; i < blimit; ++i, ++n) {
679 memcpy (bufs.get_audio (i).data(), b, sizeof (Sample) * nframes);
680 if (n < diskstream->n_channels().n_audio()) {
681 tmpb = diskstream->playback_buffer(n);
689 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
691 if (!diskstream->record_enabled() && _session.transport_rolling()) {
692 Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
694 if (am.locked() && gain_control()->automation_playback()) {
695 apply_gain_automation = gain_control()->list()->curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
699 process_output_buffers (bufs, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
702 /* problem with the diskstream; just be quiet for a bit */
703 silence (nframes, offset);
710 AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
711 bool can_record, bool rec_monitors_input)
713 if (n_outputs().n_total() == 0 && _processors.empty()) {
718 silence (nframes, offset);
723 apply_gain_automation = false;
725 silence (nframes, offset);
727 return audio_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
731 AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes, bool enable_processing)
733 gain_t gain_automation[nframes];
734 gain_t gain_buffer[nframes];
735 float mix_buffer[nframes];
736 ProcessorList::iterator i;
737 bool post_fader_work = false;
738 gain_t this_gain = _gain;
739 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
741 Glib::RWLock::ReaderLock rlock (_processor_lock);
743 boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
746 assert(buffers.get_audio(0).capacity() >= nframes);
748 if (apl->read (buffers.get_audio(0).data(), mix_buffer, gain_buffer, start, nframes) != nframes) {
752 assert(buffers.count().n_audio() >= 1);
754 Sample* b = buffers.get_audio(0).data();
755 BufferSet::audio_iterator bi = buffers.audio_begin();
757 for ( ; bi != buffers.audio_end(); ++bi, ++n) {
758 if (n < diskstream->n_channels().n_audio()) {
759 if (apl->read (bi->data(), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
765 /* duplicate last across remaining buffers */
766 memcpy (bi->data(), b, sizeof (Sample) * nframes);
770 // If no processing is required, there's no need to go any further.
771 if (!enable_processing)
774 /* note: only run processors during export. other layers in the machinery
775 will already have checked that there are no external port processors.
778 for (i = _processors.begin(); i != _processors.end(); ++i) {
779 boost::shared_ptr<Processor> processor;
781 if ((processor = boost::dynamic_pointer_cast<Processor>(*i)) != 0) {
782 switch (processor->placement()) {
784 processor->run_in_place (buffers, start, start+nframes, nframes, 0);
787 post_fader_work = true;
793 if (gain_control()->automation_state() == Play) {
795 gain_control()->list()->curve().get_vector (start, start + nframes, gain_automation, nframes);
797 for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
798 Sample *b = bi->data();
799 for (nframes_t n = 0; n < nframes; ++n) {
800 b[n] *= gain_automation[n];
806 for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
807 Sample *b = bi->data();
808 for (nframes_t n = 0; n < nframes; ++n) {
814 if (post_fader_work) {
816 for (i = _processors.begin(); i != _processors.end(); ++i) {
817 boost::shared_ptr<PluginInsert> processor;
819 if ((processor = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
820 switch ((*i)->placement()) {
824 processor->run_in_place (buffers, start, start+nframes, nframes, 0);
834 boost::shared_ptr<Region>
835 AudioTrack::bounce (InterThreadInfo& itt)
837 vector<boost::shared_ptr<Source> > srcs;
838 return _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), false, srcs, itt);
841 boost::shared_ptr<Region>
842 AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt, bool enable_processing)
844 vector<boost::shared_ptr<Source> > srcs;
845 return _session.write_one_track (*this, start, end, false, srcs, itt, enable_processing);
849 AudioTrack::freeze (InterThreadInfo& itt)
851 vector<boost::shared_ptr<Source> > srcs;
852 string new_playlist_name;
853 boost::shared_ptr<Playlist> new_playlist;
856 boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
858 if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) {
864 while (n < (UINT_MAX-1)) {
868 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
870 if (_session.playlist_by_name (candidate) == 0) {
871 new_playlist_name = candidate;
879 if (n == (UINT_MAX-1)) {
880 error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
881 " to create another one"), _freeze_record.playlist->name())
886 boost::shared_ptr<Region> res;
888 if ((res = _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) {
892 _freeze_record.processor_info.clear ();
895 Glib::RWLock::ReaderLock lm (_processor_lock);
897 for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); ++r) {
899 boost::shared_ptr<Processor> processor;
901 if ((processor = boost::dynamic_pointer_cast<Processor>(*r)) != 0) {
903 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo ((*r)->get_state(), processor);
905 frii->id = processor->id();
907 _freeze_record.processor_info.push_back (frii);
909 /* now deactivate the processor */
911 processor->deactivate ();
912 _session.set_dirty ();
917 new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
919 _freeze_record.gain = _gain;
920 _freeze_record.gain_automation_state = _gain_control->automation_state();
921 _freeze_record.pan_automation_state = _panner->automation_state();
923 region_name = new_playlist_name;
925 /* create a new region from all filesources, keep it private */
927 boost::shared_ptr<Region> region (RegionFactory::create (srcs, 0,
928 srcs[0]->length(srcs[0]->timeline_position()),
930 (Region::Flag) (Region::WholeFile|Region::DefaultFlags),
933 new_playlist->set_orig_diskstream_id (diskstream->id());
934 new_playlist->add_region (region, _session.current_start_frame());
935 new_playlist->set_frozen (true);
936 region->set_locked (true);
938 diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
939 diskstream->set_record_enabled (false);
941 /* reset stuff that has already been accounted for in the freeze process */
943 set_gain (1.0, this);
944 _gain_control->set_automation_state (Off);
945 _panner->set_automation_state (Off);
947 _freeze_record.state = Frozen;
948 FreezeChange(); /* EMIT SIGNAL */
952 AudioTrack::unfreeze ()
954 if (_freeze_record.playlist) {
955 audio_diskstream()->use_playlist (_freeze_record.playlist);
958 Glib::RWLock::ReaderLock lm (_processor_lock); // should this be a write lock? jlc
959 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
960 for (vector<FreezeRecordProcessorInfo*>::iterator ii = _freeze_record.processor_info.begin(); ii != _freeze_record.processor_info.end(); ++ii) {
961 if ((*ii)->id == (*i)->id()) {
962 (*i)->set_state (((*ii)->state));
969 _freeze_record.playlist.reset ();
970 set_gain (_freeze_record.gain, this);
971 _gain_control->set_automation_state (_freeze_record.gain_automation_state);
972 _panner->set_automation_state (_freeze_record.pan_automation_state);
975 _freeze_record.state = UnFrozen;
976 FreezeChange (); /* EMIT SIGNAL */