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