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