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