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