add muted-by-other concept to solo support infrastructure
[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
213         if (call_base) {
214                 if (Route::_set_state (node, version, call_base)) {
215                         return -1;
216                 }
217         }
218
219         if ((prop = node.property (X_("mode"))) != 0) {
220                 _mode = TrackMode (string_2_enum (prop->value(), _mode));
221         } else {
222                 _mode = Normal;
223         }
224
225         XMLNodeList nlist;
226         XMLNodeConstIterator niter;
227         XMLNode *child;
228
229         nlist = node.children();
230         for (niter = nlist.begin(); niter != nlist.end(); ++niter){
231                 child = *niter;
232
233                 if (child->name() == X_("recenable")) {
234                         _rec_enable_control->set_state (*child, version);
235                         _session.add_controllable (_rec_enable_control);
236                 }
237         }
238
239         if (version >= 3000) {
240                 if ((child = find_named_node (node, X_("Diskstream"))) != 0) {
241                         boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, *child));
242                         ds->do_refill_with_alloc ();
243                         set_diskstream (ds);
244                 }
245         }
246
247         pending_state = const_cast<XMLNode*> (&node);
248
249         if (_session.state_of_the_state() & Session::Loading) {
250                 _session.StateReady.connect_same_thread (*this, boost::bind (&AudioTrack::set_state_part_two, this));
251         } else {
252                 set_state_part_two ();
253         }
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                 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
271
272                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
273                         inode = new XMLNode (X_("processor"));
274                         (*i)->id.print (buf, sizeof (buf));
275                         inode->add_property (X_("id"), buf);
276                         inode->add_child_copy ((*i)->state);
277
278                         freeze_node->add_child_nocopy (*inode);
279                 }
280
281                 root.add_child_nocopy (*freeze_node);
282         }
283
284         root.add_property (X_("mode"), enum_2_string (_mode));
285         root.add_child_nocopy (_rec_enable_control->get_state());
286         root.add_child_nocopy (_diskstream->get_state ());
287
288         return root;
289 }
290
291 void
292 AudioTrack::set_state_part_two ()
293 {
294         XMLNode* fnode;
295         XMLProperty* prop;
296         LocaleGuard lg (X_("POSIX"));
297
298         /* This is called after all session state has been restored but before
299            have been made ports and connections are established.
300         */
301
302         if (pending_state == 0) {
303                 return;
304         }
305
306         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
307
308                 _freeze_record.state = Frozen;
309
310                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
311                         delete *i;
312                 }
313                 _freeze_record.processor_info.clear ();
314
315                 if ((prop = fnode->property (X_("playlist"))) != 0) {
316                         boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
317                         if (pl) {
318                                 _freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
319                         } else {
320                                 _freeze_record.playlist.reset ();
321                                 _freeze_record.state = NoFreeze;
322                         return;
323                         }
324                 }
325
326                 if ((prop = fnode->property (X_("state"))) != 0) {
327                         _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
328                 }
329
330                 XMLNodeConstIterator citer;
331                 XMLNodeList clist = fnode->children();
332
333                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
334                         if ((*citer)->name() != X_("processor")) {
335                                 continue;
336                         }
337
338                         if ((prop = (*citer)->property (X_("id"))) == 0) {
339                                 continue;
340                         }
341
342                         FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
343                                                                                    boost::shared_ptr<Processor>());
344                         frii->id = prop->value ();
345                         _freeze_record.processor_info.push_back (frii);
346                 }
347         }
348 }
349
350 int
351 AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
352                   bool can_record, bool rec_monitors_input, bool& need_butler)
353 {
354         int dret;
355         Sample* b;
356         Sample* tmpb;
357         nframes_t transport_frame;
358         boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
359         
360         {
361                 Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
362                 if (lm.locked()) {
363                         // automation snapshot can also be called from the non-rt context
364                         // and it uses the redirect list, so we take the lock out here
365                         automation_snapshot (start_frame, false);
366                 }
367         }
368
369         if (n_outputs().n_total() == 0 && _processors.empty()) {
370                 return 0;
371         }
372
373         if (!_active) {
374                 silence (nframes);
375                 return 0;
376         }
377
378         transport_frame = _session.transport_frame();
379
380         if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
381
382                 /* need to do this so that the diskstream sets its
383                    playback distance to zero, thus causing diskstream::commit
384                    to do nothing.
385                 */
386                 return diskstream->process (transport_frame, 0, can_record, rec_monitors_input, need_butler);
387         }
388
389         _silent = false;
390         _amp->apply_gain_automation(false);
391
392         if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input, need_butler)) != 0) {
393                 silence (nframes);
394                 return dret;
395         }
396
397         /* special condition applies */
398
399         if (_meter_point == MeterInput) {
400                 _input->process_input (_meter, start_frame, end_frame, nframes);
401         }
402
403         if (diskstream->record_enabled() && !can_record && !_session.config.get_auto_input()) {
404
405                 /* not actually recording, but we want to hear the input material anyway,
406                    at least potentially (depending on monitoring options)
407                  */
408
409                 passthru (start_frame, end_frame, nframes, false);
410
411         } else if ((b = diskstream->playback_buffer(0)) != 0) {
412
413                 /*
414                   XXX is it true that the earlier test on n_outputs()
415                   means that we can avoid checking it again here? i think
416                   so, because changing the i/o configuration of an IO
417                   requires holding the AudioEngine lock, which we hold
418                   while in the process() tree.
419                 */
420
421
422                 /* copy the diskstream data to all output buffers */
423
424                 size_t limit = input_streams ().n_audio();
425                 BufferSet& bufs = _session.get_scratch_buffers ();
426                 const size_t blimit = bufs.count().n_audio();
427
428                 uint32_t n;
429                 uint32_t i;
430
431                 if (limit > blimit) {
432
433                         /* example case: auditioner configured for stereo output,
434                            but loaded with an 8 channel file. there are only
435                            2 passthrough buffers, but n_process_buffers() will
436                            return 8.
437
438                            arbitrary decision: map all channels in the diskstream
439                            to the outputs available.
440                         */
441
442                         float scaling = limit/blimit;
443
444                         for (i = 0, n = 1; i < blimit; ++i, ++n) {
445
446                                 /* first time through just copy a channel into
447                                    the output buffer.
448                                 */
449
450                                 Sample* bb = bufs.get_audio (i).data();
451
452                                 for (nframes_t xx = 0; xx < nframes; ++xx) {
453                                         bb[xx] = b[xx] * scaling;
454                                 }
455
456                                 if (n < diskstream->n_channels().n_audio()) {
457                                         tmpb = diskstream->playback_buffer(n);
458                                         if (tmpb!=0) {
459                                                 b = tmpb;
460                                         }
461                                 }
462                         }
463
464                         for (;i < limit; ++i, ++n) {
465
466                                 /* for all remaining channels, sum with existing
467                                    data in the output buffers
468                                 */
469
470                                 bufs.get_audio (i%blimit).accumulate_with_gain_from (b, nframes, 0, scaling);
471
472                                 if (n < diskstream->n_channels().n_audio()) {
473                                         tmpb = diskstream->playback_buffer(n);
474                                         if (tmpb!=0) {
475                                                 b = tmpb;
476                                         }
477                                 }
478
479                         }
480
481                         limit = blimit;
482
483                 } else {
484                         for (i = 0, n = 1; i < limit; ++i, ++n) {
485                                 memcpy (bufs.get_audio (i).data(), b, sizeof (Sample) * nframes);
486                                 if (n < diskstream->n_channels().n_audio()) {
487                                         tmpb = diskstream->playback_buffer(n);
488                                         if (tmpb!=0) {
489                                                 b = tmpb;
490                                         }
491                                 }
492                         }
493
494                         /* try to leave any MIDI buffers alone */
495
496                         ChanCount chn;
497                         chn.set_audio (limit);
498                         chn.set_midi (_input->n_ports().n_midi());
499                         bufs.set_count (chn);
500                 }
501
502                 /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
503
504                 if (!diskstream->record_enabled() && _session.transport_rolling()) {
505 #ifdef XXX_MOVE_THIS_TO_AMP
506                         Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
507
508                         if (am.locked() && gain_control()->automation_playback()) {
509                                 _amp->apply_gain_automation(
510                                                 gain_control()->list()->curve().rt_safe_get_vector (
511                                                         start_frame, end_frame, _session.gain_automation_buffer(), nframes));
512                         }
513 #endif
514                 }
515
516                 process_output_buffers (bufs, start_frame, end_frame, nframes, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick);
517
518         } else {
519                 /* problem with the diskstream; just be quiet for a bit */
520                 silence (nframes);
521         }
522
523         return 0;
524 }
525
526 int
527 AudioTrack::export_stuff (BufferSet& buffers, sframes_t start, nframes_t nframes, bool enable_processing)
528 {
529         boost::scoped_array<gain_t> gain_buffer (new gain_t[nframes]);
530         boost::scoped_array<Sample> mix_buffer (new Sample[nframes]);
531         boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
532
533         Glib::RWLock::ReaderLock rlock (_processor_lock);
534
535         boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
536         assert(apl);
537
538         assert(buffers.get_audio(0).capacity() >= nframes);
539
540         if (apl->read (buffers.get_audio(0).data(), mix_buffer.get(), gain_buffer.get(), start, nframes) != nframes) {
541                 return -1;
542         }
543
544         assert(buffers.count().n_audio() >= 1);
545         uint32_t n=1;
546         Sample* b = buffers.get_audio(0).data();
547         BufferSet::audio_iterator bi = buffers.audio_begin();
548         ++bi;
549         for ( ; bi != buffers.audio_end(); ++bi, ++n) {
550                 if (n < diskstream->n_channels().n_audio()) {
551                         if (apl->read (bi->data(), mix_buffer.get(), gain_buffer.get(), start, nframes, n) != nframes) {
552                                 return -1;
553                         }
554                         b = bi->data();
555                 }
556                 else {
557                         /* duplicate last across remaining buffers */
558                         memcpy (bi->data(), b, sizeof (Sample) * nframes);
559                 }
560         }
561
562         // If no processing is required, there's no need to go any further.
563         if (!enable_processing) {
564                 return 0;
565         }
566
567         /* note: only run processors during export. other layers in the machinery
568            will already have checked that there are no external port processors.
569            Also, don't run deliveries that write to real output ports, and don't
570            run meters.
571         */
572
573         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
574                 boost::shared_ptr<Processor> processor = boost::dynamic_pointer_cast<Processor> (*i);
575                 boost::shared_ptr<Delivery> delivery = boost::dynamic_pointer_cast<Delivery> (*i);
576                 boost::shared_ptr<PeakMeter> meter = boost::dynamic_pointer_cast<PeakMeter> (*i);
577                 
578                 if (processor && (!delivery || !Delivery::role_requires_output_ports (delivery->role())) && !meter) {
579                         processor->run (buffers, start, start+nframes, nframes, true);
580                 }
581         }
582
583         return 0;
584 }
585
586 boost::shared_ptr<Region>
587 AudioTrack::bounce (InterThreadInfo& itt)
588 {
589         vector<boost::shared_ptr<Source> > srcs;
590         return _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), false, srcs, itt);
591 }
592
593 boost::shared_ptr<Region>
594 AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt, bool enable_processing)
595 {
596         vector<boost::shared_ptr<Source> > srcs;
597         return _session.write_one_track (*this, start, end, false, srcs, itt, enable_processing);
598 }
599
600 void
601 AudioTrack::freeze_me (InterThreadInfo& itt)
602 {
603         vector<boost::shared_ptr<Source> > srcs;
604         string new_playlist_name;
605         boost::shared_ptr<Playlist> new_playlist;
606         string dir;
607         string region_name;
608         boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
609
610         if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) {
611                 return;
612         }
613
614         uint32_t n = 1;
615
616         while (n < (UINT_MAX-1)) {
617
618                 string candidate;
619
620                 candidate = string_compose ("<F%2>%1", _freeze_record.playlist->name(), n);
621
622                 if (_session.playlists->by_name (candidate) == 0) {
623                         new_playlist_name = candidate;
624                         break;
625                 }
626
627                 ++n;
628
629         }
630
631         if (n == (UINT_MAX-1)) {
632           error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
633                             " to create another one"), _freeze_record.playlist->name())
634                << endmsg;
635                 return;
636         }
637
638         boost::shared_ptr<Region> res;
639
640         if ((res = _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) {
641                 return;
642         }
643
644         _freeze_record.processor_info.clear ();
645
646         {
647                 Glib::RWLock::ReaderLock lm (_processor_lock);
648
649                 for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); ++r) {
650
651                         boost::shared_ptr<Processor> processor;
652
653                         if ((processor = boost::dynamic_pointer_cast<Processor>(*r)) != 0) {
654
655                                 FreezeRecordProcessorInfo* frii  = new FreezeRecordProcessorInfo ((*r)->get_state(), processor);
656
657                                 frii->id = processor->id();
658
659                                 _freeze_record.processor_info.push_back (frii);
660
661                                 /* now deactivate the processor */
662
663                                 processor->deactivate ();
664                                 _session.set_dirty ();
665                         }
666                 }
667         }
668
669         new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
670
671         /* XXX need main outs automation state _freeze_record.pan_automation_state = _mainpanner->automation_state(); */
672
673         region_name = new_playlist_name;
674
675         /* create a new region from all filesources, keep it private */
676
677         PropertyList plist;
678         
679         plist.add (Properties::start, 0);
680         plist.add (Properties::length, srcs[0]->length(srcs[0]->timeline_position()));
681         plist.add (Properties::name, region_name);
682         plist.add (Properties::whole_file, true);
683
684         boost::shared_ptr<Region> region (RegionFactory::create (srcs, plist, false));
685
686         new_playlist->set_orig_diskstream_id (_diskstream->id());
687         new_playlist->add_region (region, _session.current_start_frame());
688         new_playlist->set_frozen (true);
689         region->set_locked (true);
690
691         diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
692         diskstream->set_record_enabled (false);
693
694         /* reset stuff that has already been accounted for in the freeze process */
695
696         set_gain (1.0, this);
697         _amp->gain_control()->set_automation_state (Off);
698         /* XXX need to use _main_outs _panner->set_automation_state (Off); */
699
700         _freeze_record.state = Frozen;
701         FreezeChange(); /* EMIT SIGNAL */
702 }
703
704 void
705 AudioTrack::unfreeze ()
706 {
707         if (_freeze_record.playlist) {
708                 audio_diskstream()->use_playlist (_freeze_record.playlist);
709
710                 {
711                         Glib::RWLock::ReaderLock lm (_processor_lock); // should this be a write lock? jlc
712                         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
713                                 for (vector<FreezeRecordProcessorInfo*>::iterator ii = _freeze_record.processor_info.begin(); ii != _freeze_record.processor_info.end(); ++ii) {
714                                         if ((*ii)->id == (*i)->id()) {
715                                                 (*i)->set_state (((*ii)->state), Stateful::current_state_version);
716                                                 break;
717                                         }
718                                 }
719                         }
720                 }
721
722                 _freeze_record.playlist.reset ();
723                 /* XXX need to use _main_outs _panner->set_automation_state (_freeze_record.pan_automation_state); */
724         }
725
726         _freeze_record.state = UnFrozen;
727         FreezeChange (); /* EMIT SIGNAL */
728 }
729
730 boost::shared_ptr<AudioFileSource>
731 AudioTrack::write_source (uint32_t n)
732 {
733         boost::shared_ptr<AudioDiskstream> ds = boost::dynamic_pointer_cast<AudioDiskstream> (_diskstream);
734         assert (ds);
735         return ds->write_source (n);
736 }