Remove unused method..
[ardour.git] / libs / ardour / audio_track.cc
1 /*
2     Copyright (C) 2002 Paul Davis 
3
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.
8
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.
13
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.
17
18 */
19
20 #include <sigc++/retype.h>
21 #include <sigc++/retype_return.h>
22 #include <sigc++/bind.h>
23
24 #include "pbd/error.h"
25 #include "pbd/enumwriter.h"
26
27 #include "evoral/Curve.hpp"
28
29 #include "ardour/amp.h"
30 #include "ardour/audio_buffer.h"
31 #include "ardour/audio_diskstream.h"
32 #include "ardour/audio_track.h"
33 #include "ardour/audioplaylist.h"
34 #include "ardour/audioregion.h"
35 #include "ardour/audiosource.h"
36 #include "ardour/buffer_set.h"
37 #include "ardour/io_processor.h"
38 #include "ardour/panner.h"
39 #include "ardour/playlist_factory.h"
40 #include "ardour/plugin_insert.h"
41 #include "ardour/processor.h"
42 #include "ardour/region_factory.h"
43 #include "ardour/route_group_specialized.h"
44 #include "ardour/session.h"
45 #include "ardour/utils.h"
46 #include "i18n.h"
47
48 using namespace std;
49 using namespace ARDOUR;
50 using namespace PBD;
51
52 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
53         : Track (sess, name, flag, mode)
54 {
55         use_new_diskstream ();
56 }
57
58 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
59         : Track (sess, node)
60 {
61         _set_state (node, false);
62 }
63
64 AudioTrack::~AudioTrack ()
65 {
66 }
67
68 void
69 AudioTrack::use_new_diskstream ()
70 {
71         AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
72
73         if (_flags & Hidden) {
74                 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Hidden);
75         } else {
76                 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Recordable);
77         }
78
79         if (_mode == Destructive) {
80                 dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
81         } else if (_mode == NonLayered){
82                 dflags = AudioDiskstream::Flag(dflags | AudioDiskstream::NonLayered);
83         }
84     
85
86         boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name(), dflags));
87         
88         _session.add_diskstream (ds);
89
90         set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
91 }
92
93 int
94 AudioTrack::set_mode (TrackMode m)
95 {
96         if (m != _mode) {
97
98                 if (_diskstream->set_destructive (m == Destructive)) {
99                         return -1;
100                 }
101                 
102                 _diskstream->set_non_layered (m == NonLayered);
103                 _mode = m;
104                 
105                 TrackModeChanged (); /* EMIT SIGNAL */
106         }
107
108         return 0;
109 }
110
111 bool
112 AudioTrack::can_use_mode (TrackMode m, bool& bounce_required)
113 {
114         switch (m) {
115         case NonLayered:
116         case Normal:
117                 bounce_required = false;
118                 return true;
119                 
120         case Destructive:
121         default:
122                 return _diskstream->can_become_destructive (bounce_required);
123         }
124 }
125
126 int
127 AudioTrack::deprecated_use_diskstream_connections ()
128 {
129         boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
130
131         if (diskstream->deprecated_io_node == 0) {
132                 return 0;
133         }
134
135         const XMLProperty* prop;
136         XMLNode& node (*diskstream->deprecated_io_node);
137
138         /* don't do this more than once. */
139
140         diskstream->deprecated_io_node = 0;
141
142         if ((prop = node.property ("gain")) != 0) {
143                 set_gain (atof (prop->value().c_str()), this);
144                 _gain = _gain_control->user_float();
145         }
146
147         if ((prop = node.property ("input-connection")) != 0) {
148                 boost::shared_ptr<Bundle> c = _session.bundle_by_name (prop->value());
149                 
150                 if (c == 0) {
151                         error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
152                         
153                         if ((c = _session.bundle_by_name (_("in 1"))) == 0) {
154                                 error << _("No input bundles available as a replacement")
155                                 << endmsg;
156                                 return -1;
157                         } else {
158                                 info << string_compose (_("Bundle %1 was not available - \"in 1\" used instead"), prop->value())
159                                << endmsg;
160                         }
161                 }
162
163                 connect_input_ports_to_bundle (c, this);
164
165         } else if ((prop = node.property ("inputs")) != 0) {
166                 if (set_inputs (prop->value())) {
167                         error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
168                         return -1;
169                 }
170         }
171         
172         return 0;
173 }
174
175 int
176 AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
177 {
178         _diskstream = ds;
179         _diskstream->set_io (*this);
180         _diskstream->set_destructive (_mode == Destructive);
181         _diskstream->set_non_layered (_mode == NonLayered);
182
183         if (audio_diskstream()->deprecated_io_node) {
184
185                 if (!connecting_legal) {
186                         ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
187                 } else {
188                         deprecated_use_diskstream_connections ();
189                 }
190         }
191
192         _diskstream->set_record_enabled (false);
193         _diskstream->monitor_input (false);
194
195         ic_connection.disconnect();
196         ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
197
198         DiskstreamChanged (); /* EMIT SIGNAL */
199
200         return 0;
201 }       
202
203 int 
204 AudioTrack::use_diskstream (string name)
205 {
206         boost::shared_ptr<AudioDiskstream> dstream;
207
208         if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream>(_session.diskstream_by_name (name))) == 0) {
209                 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
210                 return -1;
211         }
212         
213         return set_diskstream (dstream, this);
214 }
215
216 int 
217 AudioTrack::use_diskstream (const PBD::ID& id)
218 {
219         boost::shared_ptr<AudioDiskstream> dstream;
220
221         if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream> (_session.diskstream_by_id (id))) == 0) {
222                 error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
223                 return -1;
224         }
225         
226         return set_diskstream (dstream, this);
227 }
228
229 boost::shared_ptr<AudioDiskstream>
230 AudioTrack::audio_diskstream() const
231 {
232         return boost::dynamic_pointer_cast<AudioDiskstream>(_diskstream);
233 }
234
235 int
236 AudioTrack::set_state (const XMLNode& node)
237 {
238         return _set_state (node, true);
239 }
240
241 int
242 AudioTrack::_set_state (const XMLNode& node, bool call_base)
243 {
244         const XMLProperty *prop;
245         XMLNodeConstIterator iter;
246
247         if (call_base) {
248                 if (Route::_set_state (node, call_base)) {
249                         return -1;
250                 }
251         }
252
253         if ((prop = node.property (X_("mode"))) != 0) {
254                 _mode = TrackMode (string_2_enum (prop->value(), _mode));
255         } else {
256                 _mode = Normal;
257         }
258
259         if ((prop = node.property ("diskstream-id")) == 0) {
260                 
261                 /* some old sessions use the diskstream name rather than the ID */
262
263                 if ((prop = node.property ("diskstream")) == 0) {
264                         fatal << _("programming error: AudioTrack given state without diskstream!") << endmsg;
265                         /*NOTREACHED*/
266                         return -1;
267                 }
268
269                 if (use_diskstream (prop->value())) {
270                         return -1;
271                 }
272
273         } else {
274                 
275                 PBD::ID id (prop->value());
276                 PBD::ID zero ("0");
277                 
278                 /* this wierd hack is used when creating tracks from a template. there isn't
279                    a particularly good time to interpose between setting the first part of
280                    the track state (notably Route::set_state() and the track mode), and the
281                    second part (diskstream stuff). So, we have a special ID for the diskstream
282                    that means "you should create a new diskstream here, not look for
283                    an old one.
284                 */
285                 
286                 if (id == zero) {
287                         use_new_diskstream ();
288                 } else if (use_diskstream (id)) {
289                         return -1;
290                 }
291         }
292
293
294         XMLNodeList nlist;
295         XMLNodeConstIterator niter;
296         XMLNode *child;
297
298         nlist = node.children();
299         for (niter = nlist.begin(); niter != nlist.end(); ++niter){
300                 child = *niter;
301
302                 if (child->name() == X_("recenable")) {
303                         _rec_enable_control->set_state (*child);
304                         _session.add_controllable (_rec_enable_control);
305                 }
306         }
307
308         pending_state = const_cast<XMLNode*> (&node);
309
310         if (_session.state_of_the_state() & Session::Loading) {
311                 _session.StateReady.connect (mem_fun (*this, &AudioTrack::set_state_part_two));
312         } else {
313                 set_state_part_two ();
314         }
315
316         return 0;
317 }
318
319 XMLNode& 
320 AudioTrack::state(bool full_state)
321 {
322         XMLNode& root (Route::state(full_state));
323         XMLNode* freeze_node;
324         char buf[64];
325
326         if (_freeze_record.playlist) {
327                 XMLNode* inode;
328
329                 freeze_node = new XMLNode (X_("freeze-info"));
330                 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
331                 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
332
333                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
334                         inode = new XMLNode (X_("processor"));
335                         (*i)->id.print (buf, sizeof (buf));
336                         inode->add_property (X_("id"), buf);
337                         inode->add_child_copy ((*i)->state);
338                 
339                         freeze_node->add_child_nocopy (*inode);
340                 }
341
342                 root.add_child_nocopy (*freeze_node);
343         }
344
345         /* Alignment: act as a proxy for the diskstream */
346         
347         XMLNode* align_node = new XMLNode (X_("Alignment"));
348         AlignStyle as = _diskstream->alignment_style ();
349         align_node->add_property (X_("style"), enum_2_string (as));
350         root.add_child_nocopy (*align_node);
351
352         root.add_property (X_("mode"), enum_2_string (_mode));
353
354         /* we don't return diskstream state because we don't
355            own the diskstream exclusively. control of the diskstream
356            state is ceded to the Session, even if we create the
357            diskstream.
358         */
359
360         _diskstream->id().print (buf, sizeof (buf));
361         root.add_property ("diskstream-id", buf);
362
363         root.add_child_nocopy (_rec_enable_control->get_state());
364
365         return root;
366 }
367
368 void
369 AudioTrack::set_state_part_two ()
370 {
371         XMLNode* fnode;
372         XMLProperty* prop;
373         LocaleGuard lg (X_("POSIX"));
374
375         /* This is called after all session state has been restored but before
376            have been made ports and connections are established.
377         */
378
379         if (pending_state == 0) {
380                 return;
381         }
382
383         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
384
385                 _freeze_record.state = Frozen;
386                 
387                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
388                         delete *i;
389                 }
390                 _freeze_record.processor_info.clear ();
391                 
392                 if ((prop = fnode->property (X_("playlist"))) != 0) {
393                         boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value());
394                         if (pl) {
395                                 _freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
396                         } else {
397                                 _freeze_record.playlist.reset ();
398                                 _freeze_record.state = NoFreeze;
399                         return;
400                         }
401                 }
402                 
403                 if ((prop = fnode->property (X_("state"))) != 0) {
404                         _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
405                 }
406                 
407                 XMLNodeConstIterator citer;
408                 XMLNodeList clist = fnode->children();
409                 
410                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
411                         if ((*citer)->name() != X_("processor")) {
412                                 continue;
413                         }
414                         
415                         if ((prop = (*citer)->property (X_("id"))) == 0) {
416                                 continue;
417                         }
418                         
419                         FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
420                                                                                    boost::shared_ptr<Processor>());
421                         frii->id = prop->value ();
422                         _freeze_record.processor_info.push_back (frii);
423                 }
424         }
425
426         /* Alignment: act as a proxy for the diskstream */
427
428         if ((fnode = find_named_node (*pending_state, X_("Alignment"))) != 0) {
429
430                 if ((prop = fnode->property (X_("style"))) != 0) {
431
432                         /* fix for older sessions from before EnumWriter */
433
434                         string pstr;
435
436                         if (prop->value() == "capture") {
437                                 pstr = "CaptureTime";
438                         } else if (prop->value() == "existing") {
439                                 pstr = "ExistingMaterial";
440                         } else {
441                                 pstr = prop->value();
442                         }
443
444                         AlignStyle as = AlignStyle (string_2_enum (pstr, as));
445                         _diskstream->set_persistent_align_style (as);
446                 }
447         }
448         return;
449 }       
450
451 int
452 AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
453                   bool can_record, bool rec_monitors_input)
454 {
455         int dret;
456         Sample* b;
457         Sample* tmpb;
458         nframes_t transport_frame;
459         boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
460         
461         {
462                 Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
463                 if (lm.locked()) {
464                         // automation snapshot can also be called from the non-rt context
465                         // and it uses the redirect list, so we take the lock out here
466                         automation_snapshot (start_frame, false);
467                 }
468         }
469
470         
471         if (n_outputs().n_total() == 0 && _processors.empty()) {
472                 return 0;
473         }
474
475         if (!_active) {
476                 silence (nframes);
477                 return 0;
478         }
479
480         transport_frame = _session.transport_frame();
481
482         prepare_inputs (nframes);
483
484         if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
485
486                 /* need to do this so that the diskstream sets its
487                    playback distance to zero, thus causing diskstream::commit
488                    to do nothing.
489                 */
490                 return diskstream->process (transport_frame, 0, can_record, rec_monitors_input);
491         } 
492
493         _silent = false;
494         _amp->apply_gain_automation(false);
495
496         if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input)) != 0) {
497                 silence (nframes);
498                 return dret;
499         }
500
501         /* special condition applies */
502         
503         if (_meter_point == MeterInput) {
504                 just_meter_input (start_frame, end_frame, nframes);
505         }
506
507         if (diskstream->record_enabled() && !can_record && !_session.config.get_auto_input()) {
508
509                 /* not actually recording, but we want to hear the input material anyway,
510                    at least potentially (depending on monitoring options)
511                  */
512
513                 passthru (start_frame, end_frame, nframes, false);
514
515         } else if ((b = diskstream->playback_buffer(0)) != 0) {
516
517                 /*
518                   XXX is it true that the earlier test on n_outputs()
519                   means that we can avoid checking it again here? i think
520                   so, because changing the i/o configuration of an IO
521                   requires holding the AudioEngine lock, which we hold
522                   while in the process() tree.
523                 */
524
525                 
526                 /* copy the diskstream data to all output buffers */
527
528                 size_t limit = n_process_buffers().n_audio();
529                 BufferSet& bufs = _session.get_scratch_buffers ();
530                 const size_t blimit = bufs.count().n_audio();
531
532                 uint32_t n;
533                 uint32_t i;
534
535                 if (limit > blimit) {
536
537                         /* example case: auditioner configured for stereo output,
538                            but loaded with an 8 channel file. there are only
539                            2 passthrough buffers, but n_process_buffers() will
540                            return 8.
541                            
542                            arbitrary decision: map all channels in the diskstream
543                            to the outputs available.
544                         */
545
546                         float scaling = limit/blimit;
547                         
548                         for (i = 0, n = 1; i < blimit; ++i, ++n) {
549
550                                 /* first time through just copy a channel into 
551                                    the output buffer.
552                                 */
553                                 
554                                 Sample* bb = bufs.get_audio (i).data();
555
556                                 for (nframes_t xx = 0; xx < nframes; ++xx) {
557                                         bb[xx] = b[xx] * scaling;
558                                 }
559
560                                 if (n < diskstream->n_channels().n_audio()) {
561                                         tmpb = diskstream->playback_buffer(n);
562                                         if (tmpb!=0) {
563                                                 b = tmpb;
564                                         }
565                                 }
566                         }
567
568                         for (;i < limit; ++i, ++n) {
569                                 
570                                 /* for all remaining channels, sum with existing
571                                    data in the output buffers 
572                                 */
573                                 
574                                 bufs.get_audio (i%blimit).accumulate_with_gain_from (b, nframes, 0, scaling);
575                                 
576                                 if (n < diskstream->n_channels().n_audio()) {
577                                         tmpb = diskstream->playback_buffer(n);
578                                         if (tmpb!=0) {
579                                                 b = tmpb;
580                                         }
581                                 }
582                                 
583                         }
584
585                         limit = blimit;
586
587                 } else {
588                         for (i = 0, n = 1; i < blimit; ++i, ++n) {
589                                 memcpy (bufs.get_audio (i).data(), b, sizeof (Sample) * nframes); 
590                                 if (n < diskstream->n_channels().n_audio()) {
591                                         tmpb = diskstream->playback_buffer(n);
592                                         if (tmpb!=0) {
593                                                 b = tmpb;
594                                         }
595                                 }
596                         }
597                 }
598
599                 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
600
601                 if (!diskstream->record_enabled() && _session.transport_rolling()) {
602                         Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
603                         
604                         if (am.locked() && gain_control()->automation_playback()) {
605                                 _amp->apply_gain_automation(
606                                                 gain_control()->list()->curve().rt_safe_get_vector (
607                                                         start_frame, end_frame, _session.gain_automation_buffer(), nframes));
608                         }
609                 }
610
611                 process_output_buffers (bufs, start_frame, end_frame, nframes, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick);
612                 
613         } else {
614                 /* problem with the diskstream; just be quiet for a bit */
615                 silence (nframes);
616         }
617
618         return 0;
619 }
620
621 int
622 AudioTrack::export_stuff (BufferSet& buffers, sframes_t start, nframes_t nframes, bool enable_processing)
623 {
624         gain_t  gain_buffer[nframes];
625         float   mix_buffer[nframes];
626         ProcessorList::iterator i;
627         boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
628         
629         Glib::RWLock::ReaderLock rlock (_processor_lock);
630
631         boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
632         assert(apl);
633
634         assert(buffers.get_audio(0).capacity() >= nframes);
635
636         if (apl->read (buffers.get_audio(0).data(), mix_buffer, gain_buffer, start, nframes) != nframes) {
637                 return -1;
638         }
639
640         assert(buffers.count().n_audio() >= 1);
641         uint32_t n=1;
642         Sample* b = buffers.get_audio(0).data();
643         BufferSet::audio_iterator bi = buffers.audio_begin();
644         ++bi;
645         for ( ; bi != buffers.audio_end(); ++bi, ++n) {
646                 if (n < diskstream->n_channels().n_audio()) {
647                         if (apl->read (bi->data(), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
648                                 return -1;
649                         }
650                         b = bi->data();
651                 }
652                 else {
653                         /* duplicate last across remaining buffers */
654                         memcpy (bi->data(), b, sizeof (Sample) * nframes); 
655                 }
656         }
657
658         // If no processing is required, there's no need to go any further.
659         if (!enable_processing) {
660                 return 0;
661         }
662
663         /* note: only run processors during export. other layers in the machinery
664            will already have checked that there are no external port processors.
665         */
666         
667         for (i = _processors.begin(); i != _processors.end(); ++i) {
668                 boost::shared_ptr<Processor> processor;
669                 if ((processor = boost::dynamic_pointer_cast<Processor>(*i)) != 0) {
670                         processor->run_in_place (buffers, start, start+nframes, nframes);
671                 }
672         }
673         
674         return 0;
675 }
676
677 boost::shared_ptr<Region>
678 AudioTrack::bounce (InterThreadInfo& itt)
679 {
680         vector<boost::shared_ptr<Source> > srcs;
681         return _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), false, srcs, itt);
682 }
683
684 boost::shared_ptr<Region>
685 AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt, bool enable_processing)
686 {
687         vector<boost::shared_ptr<Source> > srcs;
688         return _session.write_one_track (*this, start, end, false, srcs, itt, enable_processing);
689 }
690
691 void
692 AudioTrack::freeze (InterThreadInfo& itt)
693 {
694         vector<boost::shared_ptr<Source> > srcs;
695         string new_playlist_name;
696         boost::shared_ptr<Playlist> new_playlist;
697         string dir;
698         string region_name;
699         boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
700         
701         if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) {
702                 return;
703         }
704
705         uint32_t n = 1;
706
707         while (n < (UINT_MAX-1)) {
708          
709                 string candidate;
710                 
711                 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
712
713                 if (_session.playlist_by_name (candidate) == 0) {
714                         new_playlist_name = candidate;
715                         break;
716                 }
717
718                 ++n;
719
720         } 
721
722         if (n == (UINT_MAX-1)) {
723           error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
724                             " to create another one"), _freeze_record.playlist->name())
725                << endmsg;
726                 return;
727         }
728
729         boost::shared_ptr<Region> res;
730
731         if ((res = _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) {
732                 return;
733         }
734
735         _freeze_record.processor_info.clear ();
736
737         {
738                 Glib::RWLock::ReaderLock lm (_processor_lock);
739                 
740                 for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); ++r) {
741                         
742                         boost::shared_ptr<Processor> processor;
743
744                         if ((processor = boost::dynamic_pointer_cast<Processor>(*r)) != 0) {
745                                 
746                                 FreezeRecordProcessorInfo* frii  = new FreezeRecordProcessorInfo ((*r)->get_state(), processor);
747                                 
748                                 frii->id = processor->id();
749
750                                 _freeze_record.processor_info.push_back (frii);
751                                 
752                                 /* now deactivate the processor */
753                                 
754                                 processor->deactivate ();
755                                 _session.set_dirty ();
756                         }
757                 }
758         }
759
760         new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
761
762         _freeze_record.gain = _gain;
763         _freeze_record.gain_automation_state = _gain_control->automation_state();
764         _freeze_record.pan_automation_state = _panner->automation_state();
765
766         region_name = new_playlist_name;
767
768         /* create a new region from all filesources, keep it private */
769
770         boost::shared_ptr<Region> region (RegionFactory::create (srcs, 0,
771                         srcs[0]->length(srcs[0]->timeline_position()), 
772                         region_name, 0,
773                         (Region::Flag) (Region::WholeFile|Region::DefaultFlags),
774                         false));
775
776         new_playlist->set_orig_diskstream_id (diskstream->id());
777         new_playlist->add_region (region, _session.current_start_frame());
778         new_playlist->set_frozen (true);
779         region->set_locked (true);
780
781         diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
782         diskstream->set_record_enabled (false);
783
784         /* reset stuff that has already been accounted for in the freeze process */
785         
786         set_gain (1.0, this);
787         _gain_control->set_automation_state (Off);
788         _panner->set_automation_state (Off);
789
790         _freeze_record.state = Frozen;
791         FreezeChange(); /* EMIT SIGNAL */
792 }
793
794 void
795 AudioTrack::unfreeze ()
796 {
797         if (_freeze_record.playlist) {
798                 audio_diskstream()->use_playlist (_freeze_record.playlist);
799
800                 {
801                         Glib::RWLock::ReaderLock lm (_processor_lock); // should this be a write lock? jlc
802                         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
803                                 for (vector<FreezeRecordProcessorInfo*>::iterator ii = _freeze_record.processor_info.begin(); ii != _freeze_record.processor_info.end(); ++ii) {
804                                         if ((*ii)->id == (*i)->id()) {
805                                                 (*i)->set_state (((*ii)->state));
806                                                 break;
807                                         }
808                                 }
809                         }
810                 }
811                 
812                 _freeze_record.playlist.reset ();
813                 set_gain (_freeze_record.gain, this);
814                 _gain_control->set_automation_state (_freeze_record.gain_automation_state);
815                 _panner->set_automation_state (_freeze_record.pan_automation_state);
816         }
817
818         _freeze_record.state = UnFrozen;
819         FreezeChange (); /* EMIT SIGNAL */
820 }
821