mechanism to allow Track (or other Route-derived type) to add its own processors...
[ardour.git] / libs / ardour / track.cc
1 /*
2     Copyright (C) 2006 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 #include "pbd/error.h"
19
20 #include "ardour/amp.h"
21 #include "ardour/audioengine.h"
22 #include "ardour/audiofilesource.h"
23 #include "ardour/audioregion.h"
24 #include "ardour/debug.h"
25 #include "ardour/delivery.h"
26 #include "ardour/disk_reader.h"
27 #include "ardour/disk_writer.h"
28 #include "ardour/event_type_map.h"
29 #include "ardour/io_processor.h"
30 #include "ardour/meter.h"
31 #include "ardour/midi_region.h"
32 #include "ardour/monitor_control.h"
33 #include "ardour/playlist.h"
34 #include "ardour/playlist_factory.h"
35 #include "ardour/port.h"
36 #include "ardour/processor.h"
37 #include "ardour/profile.h"
38 #include "ardour/region_factory.h"
39 #include "ardour/record_enable_control.h"
40 #include "ardour/record_safe_control.h"
41 #include "ardour/route_group_specialized.h"
42 #include "ardour/session.h"
43 #include "ardour/session_playlists.h"
44 #include "ardour/smf_source.h"
45 #include "ardour/track.h"
46 #include "ardour/types_convert.h"
47 #include "ardour/utils.h"
48
49 #include "pbd/i18n.h"
50
51 using namespace std;
52 using namespace ARDOUR;
53 using namespace PBD;
54
55 Track::Track (Session& sess, string name, PresentationInfo::Flag flag, TrackMode mode, DataType default_type)
56         : Route (sess, name, flag, default_type)
57         , _saved_meter_point (_meter_point)
58         , _disk_io_point (DiskIOPreFader)
59         , _mode (mode)
60         , _alignment_choice (Automatic)
61 {
62         _freeze_record.state = NoFreeze;
63         _declickable = true;
64 }
65
66 Track::~Track ()
67 {
68         DEBUG_TRACE (DEBUG::Destruction, string_compose ("track %1 destructor\n", _name));
69
70         if (_disk_reader) {
71                 _disk_reader->set_route (boost::shared_ptr<Route>());
72                 _disk_reader.reset ();
73         }
74
75         if (_disk_writer) {
76                 _disk_writer->set_route (boost::shared_ptr<Route>());
77                 _disk_writer.reset ();
78         }
79 }
80
81 int
82 Track::init ()
83 {
84         if (Route::init ()) {
85                 return -1;
86         }
87
88         use_new_playlist ();
89
90         /* disk writer and reader processors will be added when Route calls
91          * add_processors_oh_children_of_mine ().
92          */
93
94         boost::shared_ptr<Route> rp (boost::dynamic_pointer_cast<Route> (shared_from_this()));
95         boost::shared_ptr<Track> rt = boost::dynamic_pointer_cast<Track> (rp);
96
97         _record_enable_control.reset (new RecordEnableControl (_session, EventTypeMap::instance().to_symbol (RecEnableAutomation), *this));
98         add_control (_record_enable_control);
99
100         _record_safe_control.reset (new RecordSafeControl (_session, EventTypeMap::instance().to_symbol (RecSafeAutomation), *this));
101         add_control (_record_safe_control);
102
103         _monitoring_control.reset (new MonitorControl (_session, EventTypeMap::instance().to_symbol (MonitoringAutomation), *this));
104         add_control (_monitoring_control);
105
106         _session.config.ParameterChanged.connect_same_thread (*this, boost::bind (&Track::parameter_changed, this, _1));
107
108         _monitoring_control->Changed.connect_same_thread (*this, boost::bind (&Track::monitoring_changed, this, _1, _2));
109         _record_safe_control->Changed.connect_same_thread (*this, boost::bind (&Track::record_safe_changed, this, _1, _2));
110         _record_enable_control->Changed.connect_same_thread (*this, boost::bind (&Track::record_enable_changed, this, _1, _2));
111
112         _input->changed.connect_same_thread (*this, boost::bind (&Track::input_changed, this));
113
114         return 0;
115 }
116
117 void
118 Track::add_processors_oh_children_of_mine ()
119 {
120         cerr << name() << " ::apocom(), create DW + DR\n";
121
122         DiskIOProcessor::Flag dflags = DiskIOProcessor::Recordable;
123
124         if (_mode == Destructive && !Profile->get_trx()) {
125                 dflags = DiskIOProcessor::Flag (dflags | DiskIOProcessor::Destructive);
126         } else if (_mode == NonLayered){
127                 dflags = DiskIOProcessor::Flag(dflags | DiskIOProcessor::NonLayered);
128         }
129
130         _disk_reader.reset (new DiskReader (_session, name(), dflags));
131         _disk_reader->set_block_size (_session.get_block_size ());
132         _disk_reader->set_route (boost::dynamic_pointer_cast<Route> (shared_from_this()));
133
134         _disk_writer.reset (new DiskWriter (_session, name(), dflags));
135         _disk_writer->set_block_size (_session.get_block_size ());
136         _disk_writer->set_route (boost::dynamic_pointer_cast<Route> (shared_from_this()));
137 }
138
139 void
140 Track::input_changed ()
141 {
142         if (_disk_writer && _alignment_choice == Automatic) {
143                 set_align_choice_from_io ();
144         }
145 }
146
147 XMLNode&
148 Track::get_state ()
149 {
150         return state (true);
151 }
152
153 XMLNode&
154 Track::state (bool full)
155 {
156         XMLNode& root (Route::state (full));
157
158         if (_playlists[DataType::AUDIO]) {
159                 root.set_property (X_("audio-playlist"), _playlists[DataType::AUDIO]->id().to_s());
160         }
161
162         if (_playlists[DataType::MIDI]) {
163                 root.set_property (X_("midi-playlist"), _playlists[DataType::MIDI]->id().to_s());
164         }
165
166         root.add_child_nocopy (_monitoring_control->get_state ());
167         root.add_child_nocopy (_record_safe_control->get_state ());
168         root.add_child_nocopy (_record_enable_control->get_state ());
169
170         root.set_property (X_("saved-meter-point"), _saved_meter_point);
171         root.set_property (X_("disk-io-point"), _disk_io_point);
172         root.set_property (X_("alignment-choice"), _alignment_choice);
173
174         return root;
175 }
176
177 int
178 Track::set_state (const XMLNode& node, int version)
179 {
180         if (Route::set_state (node, version)) {
181                 return -1;
182         }
183
184         XMLNode* child;
185
186         if (version >= 3000 && version < 4000) {
187                 if ((child = find_named_node (node, X_("Diskstream"))) != 0) {
188                         /* XXX if we remember anything from stored DiskStream
189                            state (older Ardour versions) that is needed by a
190                            DiskReader or DiskWriter, we should cook up a new
191                            XMLNode here, populate it with that information
192                            (child nodes, properties, etc.) and then call
193                            ::set_state() on the writer/reader.
194
195                            But at present (June 2017), there's no such state.
196                         */
197                 }
198         }
199
200         std::string playlist_id;
201
202         if (node.get_property (X_("audio-playlist"), playlist_id)) {
203                 find_and_use_playlist (DataType::AUDIO, PBD::ID (playlist_id));
204         }
205
206         if (node.get_property (X_("midi-playlist"), playlist_id)) {
207                 find_and_use_playlist (DataType::MIDI, PBD::ID (playlist_id));
208         }
209
210         XMLNodeList nlist = node.children();
211         for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
212                 child = *niter;
213
214                 if (child->name() == Controllable::xml_node_name) {
215                         std::string name;
216                         if (!child->get_property ("name", name)) {
217                                 continue;
218                         }
219
220                         if (name == _record_enable_control->name()) {
221                                 _record_enable_control->set_state (*child, version);
222                         } else if (name == _record_safe_control->name()) {
223                                 _record_safe_control->set_state (*child, version);
224                         } else if (name == _monitoring_control->name()) {
225                                 _monitoring_control->set_state (*child, version);
226                         }
227                 }
228         }
229
230         if (!node.get_property (X_("saved-meter-point"), _saved_meter_point)) {
231                 _saved_meter_point = _meter_point;
232         }
233
234         if (!node.get_property (X_("saved-meter-point"), _disk_io_point)) {
235                 _disk_io_point = DiskIOPreFader;
236         }
237
238         AlignChoice ac;
239
240         if (node.get_property (X_("alignment-choice"), ac)) {
241                 set_align_choice (ac, true);
242         }
243
244         return 0;
245 }
246
247 XMLNode&
248 Track::get_template ()
249 {
250         return state (false);
251 }
252
253 Track::FreezeRecord::~FreezeRecord ()
254 {
255         for (vector<FreezeRecordProcessorInfo*>::iterator i = processor_info.begin(); i != processor_info.end(); ++i) {
256                 delete *i;
257         }
258 }
259
260 Track::FreezeState
261 Track::freeze_state() const
262 {
263         return _freeze_record.state;
264 }
265
266 bool
267 Track::can_record()
268 {
269         bool will_record = true;
270         for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end() && will_record; ++i) {
271                 if (!i->connected())
272                         will_record = false;
273         }
274
275         return will_record;
276 }
277
278 int
279 Track::prep_record_enabled (bool yn)
280 {
281         if (yn && _record_safe_control->get_value()) {
282                 return -1;
283         }
284
285         if (!can_be_record_enabled()) {
286                 return -1;
287         }
288
289         /* keep track of the meter point as it was before we rec-enabled */
290         if (!_disk_writer->record_enabled()) {
291                 _saved_meter_point = _meter_point;
292         }
293
294         bool will_follow;
295
296         if (yn) {
297                 will_follow = _disk_writer->prep_record_enable ();
298         } else {
299                 will_follow = _disk_writer->prep_record_disable ();
300         }
301
302         if (will_follow) {
303                 if (yn) {
304                         if (_meter_point != MeterCustom) {
305                                 set_meter_point (MeterInput);
306                         }
307                 } else {
308                         set_meter_point (_saved_meter_point);
309                 }
310         }
311
312         return 0;
313 }
314
315 void
316 Track::record_enable_changed (bool, Controllable::GroupControlDisposition)
317 {
318         _disk_writer->set_record_enabled (_record_enable_control->get_value());
319 }
320
321 void
322 Track::record_safe_changed (bool, Controllable::GroupControlDisposition)
323 {
324         _disk_writer->set_record_safe (_record_safe_control->get_value());
325 }
326
327 bool
328 Track::can_be_record_safe ()
329 {
330         return !_record_enable_control->get_value() && _disk_writer && _session.writable() && (_freeze_record.state != Frozen);
331 }
332
333 bool
334 Track::can_be_record_enabled ()
335 {
336         return !_record_safe_control->get_value() && _disk_writer && !_disk_writer->record_safe() && _session.writable() && (_freeze_record.state != Frozen);
337 }
338
339 void
340 Track::parameter_changed (string const & p)
341 {
342         if (p == "track-name-number") {
343                 resync_track_name ();
344         }
345         else if (p == "track-name-take") {
346                 resync_track_name ();
347         }
348         else if (p == "take-name") {
349                 if (_session.config.get_track_name_take()) {
350                         resync_track_name ();
351                 }
352         }
353 }
354
355 void
356 Track::resync_track_name ()
357 {
358         set_name(name());
359 }
360
361 bool
362 Track::set_name (const string& str)
363 {
364         bool ret;
365
366         if (str.empty ()) {
367                 return false;
368         }
369
370         if (_record_enable_control->get_value()) {
371                 /* when re-arm'ed the file (named after the track) is already ready to rolll */
372                 return false;
373         }
374
375         string diskstream_name = "";
376         if (_session.config.get_track_name_take () && !_session.config.get_take_name ().empty()) {
377                 // Note: any text is fine, legalize_for_path() fixes this later
378                 diskstream_name += _session.config.get_take_name ();
379                 diskstream_name += "_";
380         }
381         const int64_t tracknumber = track_number();
382         if (tracknumber > 0 && _session.config.get_track_name_number()) {
383                 char num[64], fmt[10];
384                 snprintf(fmt, sizeof(fmt), "%%0%d" PRId64, _session.track_number_decimals());
385                 snprintf(num, sizeof(num), fmt, tracknumber);
386                 diskstream_name += num;
387                 diskstream_name += "_";
388         }
389         diskstream_name += str;
390
391         if (diskstream_name == _diskstream_name) {
392                 return true;
393         }
394         _diskstream_name = diskstream_name;
395
396         _disk_writer->set_write_source_name (diskstream_name);
397
398         boost::shared_ptr<Track> me = boost::dynamic_pointer_cast<Track> (shared_from_this ());
399
400         if (_playlists[data_type()]->all_regions_empty () && _session.playlists->playlists_for_track (me).size() == 1) {
401                 /* Only rename the diskstream (and therefore the playlist) if
402                    a) the playlist has never had a region added to it and
403                    b) there is only one playlist for this track.
404
405                    If (a) is not followed, people can get confused if, say,
406                    they have notes about a playlist with a given name and then
407                    it changes (see mantis #4759).
408
409                    If (b) is not followed, we rename the current playlist and not
410                    the other ones, which is a bit confusing (see mantis #4977).
411                 */
412                 _disk_reader->set_name (str);
413                 _disk_writer->set_name (str);
414         }
415
416         for (uint32_t n = 0; n < DataType::num_types; ++n) {
417                 if (_playlists[n]) {
418                         _playlists[n]->set_name (str);
419                 }
420         }
421
422         /* save state so that the statefile fully reflects any filename changes */
423
424         if ((ret = Route::set_name (str)) == 0) {
425                 _session.save_state ("");
426         }
427
428         return ret;
429 }
430
431 void
432 Track::set_latency_compensation (framecnt_t longest_session_latency)
433 {
434         Route::set_latency_compensation (longest_session_latency);
435         _disk_reader->set_roll_delay (_roll_delay);
436 }
437
438 int
439 Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool session_state_changing)
440 {
441         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
442
443         if (!lm.locked()) {
444                 return 0;
445         }
446
447         bool can_record = _session.actively_recording ();
448
449         /* no outputs? nothing to do ... what happens if we have sends etc. ? */
450
451         if (n_outputs().n_total() == 0 && !ARDOUR::Profile->get_mixbus()) {
452                 //Note: Mixbus has its own output mechanism, so we should operate even if no explicit outputs are assigned
453                 return 0;
454         }
455
456         /* not active ... do the minimum possible by just outputting silence */
457
458         if (!_active) {
459                 silence (nframes);
460                 if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) {
461                         _meter->reset();
462                 }
463                 return 0;
464         }
465
466         if (session_state_changing) {
467                 if (_session.transport_speed() != 0.0f) {
468                         /* we're rolling but some state is changing (e.g. our
469                            disk reader contents) so we cannot use them. Be
470                            silent till this is over. Don't declick.
471
472                            XXX note the absurdity of ::no_roll() being called when we ARE rolling!
473                         */
474                         passthru_silence (start_frame, end_frame, nframes, 0);
475                         return 0;
476                 }
477                 /* we're really not rolling, so we're either delivery silence or actually
478                    monitoring, both of which are safe to do while session_state_changing is true.
479                 */
480         }
481
482         _disk_writer->check_record_status (start_frame, can_record);
483
484         bool be_silent;
485
486         MonitorState const s = monitoring_state ();
487         /* we are not rolling, so be silent even if we are monitoring disk, as there
488            will be no disk data coming in.
489         */
490         switch (s) {
491         case MonitoringSilence:
492                 be_silent = true;
493                 break;
494         case MonitoringDisk:
495                 be_silent = true;
496                 break;
497         case MonitoringInput:
498                 be_silent = false;
499                 break;
500         default:
501                 be_silent = false;
502                 break;
503         }
504
505         //if we have an internal generator, let it play regardless of monitoring state
506         if (_have_internal_generator) {
507                 be_silent = false;
508         }
509
510         _amp->apply_gain_automation (false);
511
512         /* if have_internal_generator, or .. */
513
514         if (be_silent) {
515
516                 if (_meter_point == MeterInput) {
517                         /* still need input monitoring and metering */
518
519                         bool const track_rec = _disk_writer->record_enabled ();
520                         bool const auto_input = _session.config.get_auto_input ();
521                         bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
522                         bool const tape_machine_mode = Config->get_tape_machine_mode ();
523                         bool no_meter = false;
524
525                         /* this needs a proper K-map
526                          * and should be separated into a function similar to monitoring_state()
527                          * that also handles roll() states in audio_track.cc, midi_track.cc and route.cc
528                          *
529                          * see http://www.oofus.co.uk/ardour/Ardour3MonitorModesV3.pdf
530                          */
531                         if (!auto_input && !track_rec) {
532                                 no_meter=true;
533                         }
534                         else if (tape_machine_mode && !track_rec && auto_input) {
535                                 no_meter=true;
536                         }
537                         else if (!software_monitor && tape_machine_mode && !track_rec) {
538                                 no_meter=true;
539                         }
540                         else if (!software_monitor && !tape_machine_mode && !track_rec && !auto_input) {
541                                 no_meter=true;
542                         }
543
544                         if (no_meter) {
545                                 BufferSet& bufs (_session.get_silent_buffers (n_process_buffers()));
546                                 _meter->run (bufs, start_frame, end_frame, 1.0, nframes, true);
547                                 _input->process_input (boost::shared_ptr<Processor>(), start_frame, end_frame, _session.transport_speed(), nframes);
548                         } else {
549                                 _input->process_input (_meter, start_frame, end_frame, _session.transport_speed(), nframes);
550                         }
551                 }
552
553                 passthru_silence (start_frame, end_frame, nframes, 0);
554
555         } else {
556
557                 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
558
559                 fill_buffers_with_input (bufs, _input, nframes);
560
561                 if (_meter_point == MeterInput) {
562                         _meter->run (bufs, start_frame, end_frame, _session.transport_speed(), nframes, true);
563                 }
564
565                 passthru (bufs, start_frame, end_frame, nframes, false);
566         }
567
568         flush_processor_buffers_locked (nframes);
569
570         return 0;
571 }
572
573 int
574 Track::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/, bool& need_butler)
575 {
576         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
577         if (!lm.locked()) {
578                 // XXX DISK reader needs to seek ahead the correct distance ?? OR DOES IT ?
579                 //framecnt_t playback_distance = _disk_reader->calculate_playback_distance(nframes);
580                 //if (can_internal_playback_seek(playback_distance)) {
581                 // internal_playback_seek(playback_distance);
582                 //}
583                 return 0;
584         }
585
586         if (n_outputs().n_total() == 0 && _processors.empty()) {
587                 return 0;
588         }
589
590         if (!_active) {
591                 silence (nframes);
592                 return 0;
593         }
594
595         _silent = true;
596         _amp->apply_gain_automation(false);
597
598         silence (nframes);
599         flush_processor_buffers_locked (nframes);
600
601         //BufferSet& bufs (_session.get_route_buffers (n_process_buffers(), true));
602         // XXXX DISKWRITER/READER ADVANCE, SET need_butler
603         return 0;
604 }
605
606 boost::shared_ptr<Playlist>
607 Track::playlist ()
608 {
609         return _playlists[data_type()];
610 }
611
612 void
613 Track::request_input_monitoring (bool m)
614 {
615         for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) {
616                 AudioEngine::instance()->request_input_monitoring ((*i)->name(), m);
617         }
618 }
619
620 void
621 Track::ensure_input_monitoring (bool m)
622 {
623         for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) {
624                 AudioEngine::instance()->ensure_input_monitoring ((*i)->name(), m);
625         }
626 }
627
628 bool
629 Track::destructive () const
630 {
631         return _disk_writer->destructive ();
632 }
633
634 list<boost::shared_ptr<Source> > &
635 Track::last_capture_sources ()
636 {
637         return _disk_writer->last_capture_sources ();
638 }
639
640 void
641 Track::update_latency_information ()
642 {
643         Glib::Threads::RWLock::ReaderLock lr (_processor_lock);
644         framecnt_t chain_latency = _input->latency ();
645
646         for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
647                 (*p)->set_input_latency (chain_latency);
648                 chain_latency += (*p)->signal_latency ();
649         }
650 }
651
652 std::string
653 Track::steal_write_source_name()
654 {
655         return _disk_writer->steal_write_source_name ();
656 }
657
658 void
659 Track::reset_write_sources (bool r, bool force)
660 {
661         _disk_writer->reset_write_sources (r, force);
662 }
663
664 float
665 Track::playback_buffer_load () const
666 {
667         return _disk_reader->buffer_load ();
668 }
669
670 float
671 Track::capture_buffer_load () const
672 {
673         return _disk_writer->buffer_load ();
674 }
675
676 int
677 Track::do_refill ()
678 {
679         return _disk_reader->do_refill ();
680 }
681
682 int
683 Track::do_flush (RunContext c, bool force)
684 {
685         return _disk_writer->do_flush (c, force);
686 }
687
688 void
689 Track::set_pending_overwrite (bool o)
690 {
691         _disk_reader->set_pending_overwrite (o);
692 }
693
694 int
695 Track::seek (framepos_t p, bool complete_refill)
696 {
697         if (_disk_reader->seek (p, complete_refill)) {
698                 return -1;
699         }
700         return _disk_writer->seek (p, complete_refill);
701 }
702
703 bool
704 Track::hidden () const
705 {
706         return _disk_writer->hidden () || _disk_reader->hidden();
707 }
708
709 int
710 Track::can_internal_playback_seek (framecnt_t p)
711 {
712         return _disk_reader->can_internal_playback_seek (p);
713 }
714
715 int
716 Track::internal_playback_seek (framecnt_t p)
717 {
718         return _disk_reader->internal_playback_seek (p);
719 }
720
721 void
722 Track::non_realtime_locate (framepos_t p)
723 {
724         Route::non_realtime_locate (p);
725
726         if (!hidden()) {
727                 /* don't waste i/o cycles and butler calls
728                    for hidden (secret) tracks
729                 */
730                 _disk_reader->non_realtime_locate (p);
731                 _disk_writer->non_realtime_locate (p);
732         }
733 }
734
735 void
736 Track::non_realtime_speed_change ()
737 {
738         _disk_reader->non_realtime_speed_change ();
739 }
740
741 int
742 Track::overwrite_existing_buffers ()
743 {
744         return _disk_reader->overwrite_existing_buffers ();
745 }
746
747 framecnt_t
748 Track::get_captured_frames (uint32_t n) const
749 {
750         return _disk_writer->get_captured_frames (n);
751 }
752
753 int
754 Track::set_loop (Location* l)
755 {
756         if (_disk_reader->set_loop (l)) {
757                 return -1;
758         }
759         return _disk_writer->set_loop (l);
760 }
761
762 void
763 Track::transport_looped (framepos_t p)
764 {
765         return _disk_writer->transport_looped (p);
766 }
767
768 bool
769 Track::realtime_speed_change ()
770 {
771         if (_disk_reader->realtime_speed_change ()) {
772                 return -1;
773         }
774         return _disk_writer->realtime_speed_change ();
775 }
776
777 void
778 Track::realtime_handle_transport_stopped ()
779 {
780         Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
781
782         if (!lm.locked ()) {
783                 return;
784         }
785
786         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
787                 (*i)->realtime_handle_transport_stopped ();
788         }
789 }
790
791 void
792 Track::transport_stopped_wallclock (struct tm & n, time_t t, bool g)
793 {
794         _disk_writer->transport_stopped_wallclock (n, t, g);
795 }
796
797 bool
798 Track::pending_overwrite () const
799 {
800         return _disk_reader->pending_overwrite ();
801 }
802
803 void
804 Track::prepare_to_stop (framepos_t t, framepos_t a)
805 {
806         _disk_writer->prepare_to_stop (t, a);
807 }
808
809 void
810 Track::set_slaved (bool s)
811 {
812         _disk_reader->set_slaved (s);
813         _disk_writer->set_slaved (s);
814 }
815
816 ChanCount
817 Track::n_channels ()
818 {
819         return _disk_reader->output_streams();
820 }
821
822 framepos_t
823 Track::get_capture_start_frame (uint32_t n) const
824 {
825         return _disk_writer->get_capture_start_frame (n);
826 }
827
828 AlignStyle
829 Track::alignment_style () const
830 {
831         return _disk_writer->alignment_style ();
832 }
833
834 AlignChoice
835 Track::alignment_choice () const
836 {
837         return _disk_writer->alignment_choice ();
838 }
839
840 framepos_t
841 Track::current_capture_start () const
842 {
843         return _disk_writer->current_capture_start ();
844 }
845
846 framepos_t
847 Track::current_capture_end () const
848 {
849         return _disk_writer->current_capture_end ();
850 }
851
852 void
853 Track::playlist_modified ()
854 {
855         _disk_reader->playlist_modified ();
856 }
857
858 int
859 Track::find_and_use_playlist (DataType dt, PBD::ID const & id)
860 {
861         boost::shared_ptr<Playlist> playlist;
862
863         if ((playlist = _session.playlists->by_id (id)) == 0) {
864                 return -1;
865         }
866
867         if (!playlist) {
868                 error << string_compose(_("DiskIOProcessor: \"%1\" isn't an playlist"), id.to_s()) << endmsg;
869                 return -1;
870         }
871
872         return use_playlist (dt, playlist);
873 }
874
875 int
876 Track::use_playlist (DataType dt, boost::shared_ptr<Playlist> p)
877 {
878         int ret;
879
880         if ((ret = _disk_reader->use_playlist (dt, p)) == 0) {
881                 if ((ret = _disk_writer->use_playlist (dt, p)) == 0) {
882                         p->set_orig_track_id (id());
883                 }
884         }
885
886         if (ret == 0) {
887                 _playlists[dt] = p;
888         }
889
890         return ret;
891 }
892
893 int
894 Track::use_copy_playlist ()
895 {
896         assert (_playlists[data_type()]);
897
898         if (_playlists[data_type()] == 0) {
899                 error << string_compose(_("DiskIOProcessor %1: there is no existing playlist to make a copy of!"), _name) << endmsg;
900                 return -1;
901         }
902
903         string newname;
904         boost::shared_ptr<Playlist> playlist;
905
906         newname = Playlist::bump_name (_playlists[data_type()]->name(), _session);
907
908         if ((playlist = PlaylistFactory::create (_playlists[data_type()], newname)) == 0) {
909                 return -1;
910         }
911
912         playlist->reset_shares();
913
914         return use_playlist (data_type(), playlist);
915 }
916
917 int
918 Track::use_new_playlist ()
919 {
920         string newname;
921         boost::shared_ptr<Playlist> playlist = _playlists[data_type()];
922
923         if (playlist) {
924                 newname = Playlist::bump_name (playlist->name(), _session);
925         } else {
926                 newname = Playlist::bump_name (_name, _session);
927         }
928
929         playlist = PlaylistFactory::create (data_type(), _session, newname, hidden());
930
931         if (!playlist) {
932                 return -1;
933         }
934
935         return use_playlist (data_type(), playlist);
936 }
937
938 void
939 Track::set_align_choice (AlignChoice ac, bool force)
940 {
941         switch (ac) {
942         case Automatic:
943                 _alignment_choice = Automatic;
944                 set_align_choice_from_io ();
945                 return;
946         default:
947                 break;
948         }
949
950         _disk_writer->set_align_choice (ac, force);
951         _alignment_choice = ac;
952 }
953
954 void
955 Track::set_align_style (AlignStyle s, bool force)
956 {
957         _disk_writer->set_align_style (s, force);
958 }
959
960 void
961 Track::set_align_choice_from_io ()
962 {
963         bool have_physical = false;
964
965         if (_input) {
966                 uint32_t n = 0;
967                 vector<string> connections;
968                 boost::shared_ptr<Port> p;
969
970                 while (true) {
971
972                         p = _input->nth (n++);
973
974                         if (!p) {
975                                 break;
976                         }
977
978                         if (p->get_connections (connections) != 0) {
979                                 if (AudioEngine::instance()->port_is_physical (connections[0])) {
980                                         have_physical = true;
981                                         break;
982                                 }
983                         }
984
985                         connections.clear ();
986                 }
987         }
988
989 #ifdef MIXBUS
990         // compensate for latency when bouncing from master or mixbus.
991         // we need to use "ExistingMaterial" to pick up the master bus' latency
992         // see also Route::direct_feeds_according_to_reality
993         IOVector ios;
994         ios.push_back (_input);
995         if (_session.master_out() && ios.fed_by (_session.master_out()->output())) {
996                 have_physical = true;
997         }
998         for (uint32_t n = 0; n < NUM_MIXBUSES && !have_physical; ++n) {
999                 if (_session.get_mixbus (n) && ios.fed_by (_session.get_mixbus(n)->output())) {
1000                         have_physical = true;
1001                 }
1002         }
1003 #endif
1004
1005         if (have_physical) {
1006                 _disk_writer->set_align_style (ExistingMaterial);
1007         } else {
1008                 _disk_writer->set_align_style (CaptureTime);
1009         }
1010 }
1011
1012 void
1013 Track::set_block_size (pframes_t n)
1014 {
1015         Route::set_block_size (n);
1016         _disk_reader->set_block_size (n);
1017         _disk_writer->set_block_size (n);
1018 }
1019
1020 void
1021 Track::adjust_playback_buffering ()
1022 {
1023         if (_disk_reader) {
1024                 _disk_reader->adjust_buffering ();
1025         }
1026 }
1027
1028 void
1029 Track::adjust_capture_buffering ()
1030 {
1031         if (_disk_writer) {
1032                 _disk_writer->adjust_buffering ();
1033         }
1034 }
1035
1036 #ifdef USE_TRACKS_CODE_FEATURES
1037
1038 /* This is the Tracks version of Track::monitoring_state().
1039  *
1040  * Ardour developers: try to flag or fix issues if parts of the libardour API
1041  * change in ways that invalidate this
1042  */
1043
1044 MonitorState
1045 Track::monitoring_state () const
1046 {
1047         /* Explicit requests */
1048
1049         if (_monitoring != MonitorInput) {
1050                 return MonitoringInput;
1051         }
1052
1053         if (_monitoring & MonitorDisk) {
1054                 return MonitoringDisk;
1055         }
1056
1057         /* This is an implementation of the truth table in doc/monitor_modes.pdf;
1058            I don't think it's ever going to be too pretty too look at.
1059         */
1060
1061         // GZ: NOT USED IN TRACKS
1062         //bool const auto_input = _session.config.get_auto_input ();
1063         //bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
1064         //bool const tape_machine_mode = Config->get_tape_machine_mode ();
1065
1066         bool const roll = _session.transport_rolling ();
1067         bool const track_rec = _diskstream->record_enabled ();
1068         bool session_rec = _session.actively_recording ();
1069
1070         if (track_rec) {
1071
1072                 if (!session_rec && roll) {
1073                         return MonitoringDisk;
1074                 } else {
1075                         return MonitoringInput;
1076                 }
1077
1078         } else {
1079
1080                 if (roll) {
1081                         return MonitoringDisk;
1082                 }
1083         }
1084
1085         return MonitoringSilence;
1086 }
1087
1088 #else
1089
1090 /* This is the Ardour/Mixbus version of Track::monitoring_state().
1091  *
1092  * Tracks developers: do NOT modify this method under any circumstances.
1093  */
1094
1095 MonitorState
1096 Track::monitoring_state () const
1097 {
1098         /* Explicit requests */
1099         MonitorChoice m (_monitoring_control->monitoring_choice());
1100
1101         if (m != MonitorAuto) {
1102
1103                 MonitorState ms ((MonitorState) 0);
1104
1105                 if (m & MonitorInput) {
1106                         ms = MonitoringInput;
1107                 }
1108
1109                 if (m & MonitorDisk) {
1110                         ms = MonitorState (ms | MonitoringDisk);
1111                 }
1112
1113                 return ms;
1114         }
1115
1116         switch (_session.config.get_session_monitoring ()) {
1117                 case MonitorDisk:
1118                         return MonitoringDisk;
1119                         break;
1120                 case MonitorInput:
1121                         return MonitoringInput;
1122                         break;
1123                 default:
1124                         break;
1125         }
1126
1127         /* This is an implementation of the truth table in doc/monitor_modes.pdf;
1128            I don't think it's ever going to be too pretty too look at.
1129         */
1130
1131         bool const roll = _session.transport_rolling ();
1132         bool const track_rec = _disk_writer->record_enabled ();
1133         bool const auto_input = _session.config.get_auto_input ();
1134         bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
1135         bool const tape_machine_mode = Config->get_tape_machine_mode ();
1136         bool session_rec;
1137
1138         /* I suspect that just use actively_recording() is good enough all the
1139          * time, but just to keep the semantics the same as they were before
1140          * sept 26th 2012, we differentiate between the cases where punch is
1141          * enabled and those where it is not.
1142          *
1143          * rg: I suspect this is not the case: monitoring may differ
1144          */
1145
1146         if (_session.config.get_punch_in() || _session.config.get_punch_out() || _session.preroll_record_punch_enabled ()) {
1147                 session_rec = _session.actively_recording ();
1148         } else {
1149                 session_rec = _session.get_record_enabled();
1150         }
1151
1152         if (track_rec) {
1153
1154                 if (!session_rec && roll && auto_input) {
1155                         return MonitoringDisk;
1156                 } else {
1157                         return software_monitor ? MonitoringInput : MonitoringSilence;
1158                 }
1159
1160         } else {
1161
1162                 if (tape_machine_mode) {
1163
1164                         return MonitoringDisk;
1165
1166                 } else {
1167
1168                         if (!roll && auto_input) {
1169                                 return software_monitor ? MonitoringInput : MonitoringSilence;
1170                         } else {
1171                                 return MonitoringDisk;
1172                         }
1173
1174                 }
1175         }
1176
1177         abort(); /* NOTREACHED */
1178         return MonitoringSilence;
1179 }
1180
1181 #endif
1182
1183 void
1184 Track::maybe_declick (BufferSet& bufs, framecnt_t nframes, int declick)
1185 {
1186         /* never declick if there is an internal generator - we just want it to
1187            keep generating sound without interruption.
1188
1189            ditto if we are monitoring inputs.
1190         */
1191
1192         if (_have_internal_generator || (_monitoring_control->monitoring_choice() == MonitorInput)) {
1193                 return;
1194         }
1195
1196         if (!declick) {
1197                 declick = _pending_declick;
1198         }
1199
1200         if (declick != 0) {
1201                 Amp::declick (bufs, nframes, declick);
1202         }
1203 }
1204
1205 framecnt_t
1206 Track::check_initial_delay (framecnt_t nframes, framepos_t& transport_frame)
1207 {
1208         if (_roll_delay > nframes) {
1209
1210                 _roll_delay -= nframes;
1211                 silence_unlocked (nframes);
1212                 /* transport frame is not legal for caller to use */
1213                 return 0;
1214
1215         } else if (_roll_delay > 0) {
1216
1217                 nframes -= _roll_delay;
1218                 silence_unlocked (_roll_delay);
1219                 transport_frame += _roll_delay;
1220
1221                 /* shuffle all the port buffers for things that lead "out" of this Route
1222                    to reflect that we just wrote _roll_delay frames of silence.
1223                 */
1224
1225                 Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
1226                 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
1227                         boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor> (*i);
1228                         if (iop) {
1229                                 iop->increment_port_buffer_offset (_roll_delay);
1230                         }
1231                 }
1232                 _output->increment_port_buffer_offset (_roll_delay);
1233
1234                 _roll_delay = 0;
1235
1236         }
1237
1238         return nframes;
1239 }
1240
1241 void
1242 Track::monitoring_changed (bool, Controllable::GroupControlDisposition)
1243 {
1244         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
1245                 (*i)->monitoring_changed ();
1246         }
1247 }
1248
1249 MeterState
1250 Track::metering_state () const
1251 {
1252         bool rv;
1253         if (_session.transport_rolling ()) {
1254                 // audio_track.cc || midi_track.cc roll() runs meter IFF:
1255                 rv = _meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled());
1256         } else {
1257                 // track no_roll() always metering if
1258                 rv = _meter_point == MeterInput;
1259         }
1260         return rv ? MeteringInput : MeteringRoute;
1261 }
1262
1263 bool
1264 Track::set_processor_state (XMLNode const & node, XMLProperty const* prop, ProcessorList& new_order, bool& must_configure)
1265 {
1266         if (Route::set_processor_state (node, prop, new_order, must_configure)) {
1267                 return true;
1268         }
1269
1270         if (prop->value() == "diskreader") {
1271                 if (_disk_reader) {
1272                         _disk_reader->set_state (node, Stateful::current_state_version);
1273                         new_order.push_back (_disk_reader);
1274                         return true;
1275                 }
1276         } else if (prop->value() == "diskwriter") {
1277                 if (_disk_writer) {
1278                         _disk_writer->set_state (node, Stateful::current_state_version);
1279                         new_order.push_back (_disk_writer);
1280                         return true;
1281                 }
1282         }
1283
1284         error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
1285         return false;
1286 }
1287
1288 void
1289 Track::use_captured_sources (SourceList& srcs, CaptureInfos const & capture_info)
1290 {
1291         if (srcs.empty()) {
1292                 return;
1293         }
1294
1295         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (srcs.front());
1296         boost::shared_ptr<SMFSource> mfs = boost::dynamic_pointer_cast<SMFSource> (srcs.front());
1297
1298         if (afs) {
1299                 use_captured_audio_sources (srcs, capture_info);
1300         }
1301
1302         if (mfs) {
1303                 use_captured_midi_sources (srcs, capture_info);
1304         }
1305 }
1306
1307 void
1308 Track::use_captured_midi_sources (SourceList& srcs, CaptureInfos const & capture_info)
1309 {
1310         if (srcs.empty() || data_type() != DataType::MIDI) {
1311                 return;
1312         }
1313
1314         boost::shared_ptr<SMFSource> mfs = boost::dynamic_pointer_cast<SMFSource> (srcs.front());
1315         boost::shared_ptr<Playlist> pl = _playlists[DataType::MIDI];
1316         boost::shared_ptr<MidiRegion> midi_region;
1317         CaptureInfos::const_iterator ci;
1318
1319         if (!mfs || !pl) {
1320                 return;
1321         }
1322
1323         framecnt_t total_capture = 0;
1324
1325         for (total_capture = 0, ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1326                 total_capture += (*ci)->frames;
1327         }
1328
1329         /* we will want to be able to keep (over)writing the source
1330            but we don't want it to be removable. this also differs
1331            from the audio situation, where the source at this point
1332            must be considered immutable. luckily, we can rely on
1333            MidiSource::mark_streaming_write_completed() to have
1334            already done the necessary work for that.
1335         */
1336
1337         string whole_file_region_name;
1338         whole_file_region_name = region_name_from_path (mfs->name(), true);
1339
1340         /* Register a new region with the Session that
1341            describes the entire source. Do this first
1342            so that any sub-regions will obviously be
1343            children of this one (later!)
1344         */
1345
1346         try {
1347                 PropertyList plist;
1348
1349                 plist.add (Properties::name, whole_file_region_name);
1350                 plist.add (Properties::whole_file, true);
1351                 plist.add (Properties::automatic, true);
1352                 plist.add (Properties::start, 0);
1353                 plist.add (Properties::length, total_capture);
1354                 plist.add (Properties::layer, 0);
1355
1356                 boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
1357
1358                 midi_region = boost::dynamic_pointer_cast<MidiRegion> (rx);
1359                 midi_region->special_set_position (capture_info.front()->start);
1360         }
1361
1362         catch (failed_constructor& err) {
1363                 error << string_compose(_("%1: could not create region for complete midi file"), _name) << endmsg;
1364                 /* XXX what now? */
1365         }
1366
1367         pl->clear_changes ();
1368         pl->freeze ();
1369
1370         /* Session frame time of the initial capture in this pass, which is where the source starts */
1371         framepos_t initial_capture = 0;
1372         if (!capture_info.empty()) {
1373                 initial_capture = capture_info.front()->start;
1374         }
1375
1376         BeatsFramesConverter converter (_session.tempo_map(), capture_info.front()->start);
1377         const framepos_t preroll_off = _session.preroll_record_trim_len ();
1378
1379         for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1380
1381                 string region_name;
1382
1383                 RegionFactory::region_name (region_name, mfs->name(), false);
1384
1385                 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 capture start @ %2 length %3 add new region %4\n",
1386                                                                       _name, (*ci)->start, (*ci)->frames, region_name));
1387
1388
1389                 // cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add a region\n";
1390
1391                 try {
1392                         PropertyList plist;
1393
1394                         /* start of this region is the offset between the start of its capture and the start of the whole pass */
1395                         plist.add (Properties::start, (*ci)->start - initial_capture);
1396                         plist.add (Properties::length, (*ci)->frames);
1397                         plist.add (Properties::length_beats, converter.from((*ci)->frames).to_double());
1398                         plist.add (Properties::name, region_name);
1399
1400                         boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
1401                         midi_region = boost::dynamic_pointer_cast<MidiRegion> (rx);
1402                         if (preroll_off > 0) {
1403                                 midi_region->trim_front ((*ci)->start - initial_capture + preroll_off);
1404                         }
1405                 }
1406
1407                 catch (failed_constructor& err) {
1408                         error << _("MidiDiskstream: could not create region for captured midi!") << endmsg;
1409                         continue; /* XXX is this OK? */
1410                 }
1411
1412                 // cerr << "add new region, buffer position = " << buffer_position << " @ " << (*ci)->start << endl;
1413
1414                 pl->add_region (midi_region, (*ci)->start + preroll_off);
1415         }
1416
1417         pl->thaw ();
1418         _session.add_command (new StatefulDiffCommand (pl));
1419 }
1420
1421 void
1422 Track::use_captured_audio_sources (SourceList& srcs, CaptureInfos const & capture_info)
1423 {
1424         if (srcs.empty() || data_type() != DataType::AUDIO) {
1425                 return;
1426         }
1427
1428         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (srcs.front());
1429         boost::shared_ptr<Playlist> pl = _playlists[DataType::AUDIO];
1430         boost::shared_ptr<AudioRegion> region;
1431
1432         if (!afs || !pl) {
1433                 return;
1434         }
1435
1436         /* destructive tracks have a single, never changing region */
1437
1438         if (destructive()) {
1439
1440                 /* send a signal that any UI can pick up to do the right thing. there is
1441                    a small problem here in that a UI may need the peak data to be ready
1442                    for the data that was recorded and this isn't interlocked with that
1443                    process. this problem is deferred to the UI.
1444                  */
1445
1446                 pl->LayeringChanged(); // XXX this may not get the UI to do the right thing
1447                 return;
1448         }
1449
1450         string whole_file_region_name;
1451         whole_file_region_name = region_name_from_path (afs->name(), true);
1452
1453         /* Register a new region with the Session that
1454            describes the entire source. Do this first
1455            so that any sub-regions will obviously be
1456            children of this one (later!)
1457         */
1458
1459         try {
1460                 PropertyList plist;
1461
1462                 plist.add (Properties::start, afs->last_capture_start_frame());
1463                 plist.add (Properties::length, afs->length(0));
1464                 plist.add (Properties::name, whole_file_region_name);
1465                 boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
1466                 rx->set_automatic (true);
1467                 rx->set_whole_file (true);
1468
1469                 region = boost::dynamic_pointer_cast<AudioRegion> (rx);
1470                 region->special_set_position (afs->natural_position());
1471         }
1472
1473
1474         catch (failed_constructor& err) {
1475                 error << string_compose(_("%1: could not create region for complete audio file"), _name) << endmsg;
1476                 /* XXX what now? */
1477         }
1478
1479         pl->clear_changes ();
1480         pl->set_capture_insertion_in_progress (true);
1481         pl->freeze ();
1482
1483         const framepos_t preroll_off = _session.preroll_record_trim_len ();
1484         framecnt_t buffer_position = afs->last_capture_start_frame ();
1485         CaptureInfos::const_iterator ci;
1486
1487         for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1488
1489                 string region_name;
1490
1491                 RegionFactory::region_name (region_name, whole_file_region_name, false);
1492
1493                 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 capture bufpos %5 start @ %2 length %3 add new region %4\n",
1494                                                                       _name, (*ci)->start, (*ci)->frames, region_name, buffer_position));
1495
1496                 try {
1497
1498                         PropertyList plist;
1499
1500                         plist.add (Properties::start, buffer_position);
1501                         plist.add (Properties::length, (*ci)->frames);
1502                         plist.add (Properties::name, region_name);
1503
1504                         boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
1505                         region = boost::dynamic_pointer_cast<AudioRegion> (rx);
1506                         if (preroll_off > 0) {
1507                                 region->trim_front (buffer_position + preroll_off);
1508                         }
1509                 }
1510
1511                 catch (failed_constructor& err) {
1512                         error << _("AudioDiskstream: could not create region for captured audio!") << endmsg;
1513                         continue; /* XXX is this OK? */
1514                 }
1515
1516                 pl->add_region (region, (*ci)->start + preroll_off, 1, _disk_writer->non_layered());
1517                 pl->set_layer (region, DBL_MAX);
1518
1519                 buffer_position += (*ci)->frames;
1520         }
1521
1522         pl->thaw ();
1523         pl->set_capture_insertion_in_progress (false);
1524         _session.add_command (new StatefulDiffCommand (pl));
1525 }
1526
1527 #ifdef __clang__
1528 __attribute__((annotate("realtime")))
1529 #endif
1530 void
1531 Track::setup_invisible_processors_oh_children_of_mine (ProcessorList& processors)
1532 {
1533         ProcessorList::iterator insert_pos;
1534
1535         switch (_disk_io_point) {
1536         case DiskIOPreFader:
1537                 insert_pos = find (processors.begin(), processors.end(), _trim);
1538                 if (insert_pos != processors.end()) {
1539                         insert_pos = processors.insert (insert_pos, _disk_writer);
1540                         processors.insert (insert_pos, _disk_reader);
1541                 }
1542                 break;
1543         case DiskIOPostFader:
1544                 insert_pos = find (processors.begin(), processors.end(), _main_outs);
1545                 if (insert_pos != processors.end()) {
1546                         insert_pos = processors.insert (insert_pos, _disk_writer);
1547                         processors.insert (insert_pos, _disk_reader);
1548                 }
1549         case DiskIOCustom:
1550                 break;
1551         }
1552 }
1553
1554 void
1555 Track::set_disk_io_position (DiskIOPoint diop)
1556 {
1557         bool display = false;
1558
1559         switch (diop) {
1560         case DiskIOCustom:
1561                 display = true;
1562                 break;
1563         default:
1564                 display = false;
1565         }
1566
1567         _disk_writer->set_display_to_user (display);
1568         _disk_reader->set_display_to_user (display);
1569
1570         const bool changed = (diop != _disk_io_point);
1571
1572         _disk_io_point = diop;
1573
1574         if (changed) {
1575                 Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
1576                 configure_processors (0);
1577         }
1578 }