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