~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to libs/ardour/audio_track.cc

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

Show diffs side-by-side

added added

removed removed

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