2 Copyright (C) 1999-2003 Paul Davis
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.
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.
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.
25 #include <sigc++/bind.h>
26 #include <sigc++/retype.h>
29 #include <pbd/error.h>
30 #include <pbd/lockmonitor.h>
31 #include <pbd/pthread_utils.h>
33 #include <midi++/mmc.h>
34 #include <midi++/port.h>
36 #include <ardour/ardour.h>
37 #include <ardour/audioengine.h>
38 #include <ardour/session.h>
39 #include <ardour/diskstream.h>
40 #include <ardour/auditioner.h>
41 #include <ardour/slave.h>
42 #include <ardour/location.h>
47 using namespace ARDOUR;
51 Session::request_input_change_handling ()
53 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
58 Session::request_slave_source (SlaveSource src, jack_nframes_t pos)
60 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, pos, 0.0);
62 if (src == Session::JACK) {
63 /* could set_seamless_loop() be disposed of entirely?*/
64 set_seamless_loop (false);
67 set_seamless_loop (true);
74 Session::request_transport_speed (float speed)
76 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
81 Session::request_diskstream_speed (DiskStream& ds, float speed)
83 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
89 Session::request_stop (bool abort)
91 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
96 Session::request_locate (jack_nframes_t target_frame, bool with_roll)
98 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
103 Session::force_locate (jack_nframes_t target_frame, bool with_roll)
105 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
110 Session::request_auto_loop (bool yn)
113 Location *location = _locations.auto_loop_location();
115 if (location == 0 && yn) {
116 error << _("Cannot loop - no loop range defined")
121 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
124 if (!yn && seamless_loop && transport_rolling()) {
125 // request an immediate locate to refresh the diskstreams
126 // after disabling looping
127 request_locate (_transport_frame-1, true);
132 Session::set_seamless_loop (bool yn)
134 if (seamless_loop != yn) {
137 if (auto_loop && transport_rolling()) {
138 // to reset diskstreams etc
139 request_auto_loop (true);
142 ControlChanged (SeamlessLoop); /* EMIT */
147 Session::realtime_stop (bool abort)
149 /* assume that when we start, we'll be moving forwards */
151 if (_transport_speed < 0.0f) {
152 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
154 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
157 if (actively_recording()) {
159 /* move the transport position back to where the
160 request for a stop was noticed. we rolled
161 past that point to pick up delayed input.
164 #ifndef LEAVE_TRANSPORT_UNADJUSTED
165 decrement_transport_position (_worst_output_latency);
168 if (_transport_frame > current_end_frame()) {
170 /* first capture resets end location; later captures can only extend the length */
172 if (_end_location_is_free) {
173 end_location->set_end (_transport_frame);
174 _end_location_is_free = false;
175 } else if (_transport_frame > end_location->start()) {
176 end_location->set_end (_transport_frame);
179 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
185 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
188 _clear_event_type (Event::StopOnce);
189 _clear_event_type (Event::RangeStop);
190 _clear_event_type (Event::RangeLocate);
194 reset_slave_state ();
196 _transport_speed = 0;
197 transport_sub_state = (auto_return ? AutoReturning : 0);
201 Session::butler_transport_work ()
203 if (post_transport_work & PostTransportCurveRealloc) {
204 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
205 (*i)->curve_reallocate();
209 if (post_transport_work & PostTransportInputChange) {
210 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
211 (*i)->non_realtime_input_change ();
215 if (post_transport_work & PostTransportSpeed) {
216 non_realtime_set_speed ();
219 if (post_transport_work & PostTransportReverse) {
223 cumulative_rf_motion = 0;
226 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
227 if (!(*i)->hidden()) {
228 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
229 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
232 (*i)->seek (_transport_frame);
238 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
239 non_realtime_stop (post_transport_work & PostTransportAbort);
242 if (post_transport_work & PostTransportOverWrite) {
243 non_realtime_overwrite ();
246 if (post_transport_work & PostTransportAudition) {
247 non_realtime_set_audition ();
250 atomic_dec (&butler_should_do_transport_work);
254 Session::non_realtime_set_speed ()
256 LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
258 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
259 (*i)->non_realtime_set_speed ();
264 Session::non_realtime_overwrite ()
266 LockMonitor lm (diskstream_lock, __LINE__, __FILE__);
268 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
269 if ((*i)->pending_overwrite) {
270 (*i)->overwrite_existing_buffers ();
276 Session::non_realtime_stop (bool abort)
284 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
285 if ((*i)->get_captured_frames () != 0) {
291 /* stop and locate are merged here because they share a lot of common stuff */
294 now = localtime (&xnow);
297 auditioner->cancel_audition ();
301 cumulative_rf_motion = 0;
305 begin_reversible_command ("capture");
307 Location* loc = _locations.end_location();
309 if (loc && !_have_captured) {
313 note: later captures that extend the session length get
314 handled because of playlist length changes.
317 add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
318 add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
321 _have_captured = true;
324 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
325 (*i)->transport_stopped (*now, xnow, abort);
328 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
329 if (!(*i)->hidden()) {
330 (*i)->set_pending_declick (0);
335 commit_reversible_command ();
338 if (_engine.running()) {
339 update_latency_compensation (true, abort);
342 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
344 if (pending_locate_flush) {
345 flush_all_redirects ();
348 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
350 _transport_frame = last_stop_frame;
352 if (synced_to_jack()) {
353 _engine.transport_locate (_transport_frame);
357 #ifndef LEAVE_TRANSPORT_UNADJUSTED
361 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
362 if (!(*i)->hidden()) {
363 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
364 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
367 (*i)->seek (_transport_frame);
372 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
374 #ifdef LEAVE_TRANSPORT_UNADJUSTED
378 last_stop_frame = _transport_frame;
380 send_full_time_code ();
381 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
382 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
385 atomic_set (&_record_status, Disabled);
386 RecordDisabled (); /* EMIT SIGNAL */
389 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
390 /* capture start has been changed, so save pending state */
391 save_state ("", true);
394 /* save the current state of things if appropriate */
397 save_state (_current_snapshot_name);
400 if (post_transport_work & PostTransportDuration) {
401 DurationChanged (); /* EMIT SIGNAL */
404 if (post_transport_work & PostTransportStop) {
407 /* do not turn off autoloop on stop */
411 PositionChanged (_transport_frame); /* EMIT SIGNAL */
412 TransportStateChange (); /* EMIT SIGNAL */
414 /* and start it up again if relevant */
416 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
417 request_transport_speed (1.0);
418 pending_locate_roll = false;
423 Session::check_declick_out ()
425 bool locate_required = transport_sub_state & PendingLocate;
427 /* this is called after a process() iteration. if PendingDeclickOut was set,
428 it means that we were waiting to declick the output (which has just been
429 done) before doing something else. this is where we do that "something else".
431 note: called from the audio thread.
434 if (transport_sub_state & PendingDeclickOut) {
436 if (locate_required) {
437 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
438 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
440 stop_transport (pending_abort);
441 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
447 Session::set_auto_loop (bool yn)
449 /* Called from event-handling context */
451 if (actively_recording() || _locations.auto_loop_location() == 0) {
457 if (yn && seamless_loop && synced_to_jack()) {
458 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
459 "Recommend changing the configured options")
465 if ((auto_loop = yn)) {
470 if ((loc = _locations.auto_loop_location()) != 0) {
473 // set all diskstreams to use internal looping
474 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
475 if (!(*i)->hidden()) {
476 (*i)->set_loop (loc);
481 // set all diskstreams to NOT use internal looping
482 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
483 if (!(*i)->hidden()) {
489 /* stick in the loop event */
491 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
494 /* locate to start of loop and roll if current pos is outside of the loop range */
495 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
496 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
500 // locate to current position (+ 1 to force reload)
501 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
509 clear_events (Event::AutoLoop);
511 // set all diskstreams to NOT use internal looping
512 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
513 if (!(*i)->hidden()) {
520 ControlChanged (AutoLoop); /* EMIT SIGNAL */
524 Session::flush_all_redirects ()
526 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
527 (*i)->flush_redirects ();
532 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
534 if (synced_to_jack()) {
539 _slave->speed_and_position (sp, pos);
541 if (target_frame != pos) {
543 /* tell JACK to change transport position, and we will
544 follow along later in ::follow_slave()
547 _engine.transport_locate (target_frame);
549 if (sp != 1.0f && with_roll) {
550 _engine.transport_start ();
557 locate (target_frame, with_roll, with_flush, with_loop);
562 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
564 if (actively_recording()) {
568 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
570 set_transport_speed (1.0, false);
572 loop_changing = false;
576 _transport_frame = target_frame;
578 if (_transport_speed && (!with_loop || loop_changing)) {
579 /* schedule a declick. we'll be called again when its done */
581 if (!(transport_sub_state & PendingDeclickOut)) {
582 transport_sub_state |= (PendingDeclickOut|PendingLocate);
583 pending_locate_frame = target_frame;
584 pending_locate_roll = with_roll;
585 pending_locate_flush = with_flush;
590 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
591 realtime_stop (false);
594 if ( !with_loop || loop_changing) {
596 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
599 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
602 schedule_butler_transport_work ();
606 /* XXX i don't know where else to put this. something has to clear the
607 current clicks, and without deadlocking. clear_clicks() takes
608 the route lock which would deadlock in this context.
611 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
619 /* cancel autoloop if transport pos outside of loop range */
621 Location* al = _locations.auto_loop_location();
623 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
624 // cancel looping directly, this is called from event handling context
625 set_auto_loop(false);
629 loop_changing = false;
633 Session::set_transport_speed (float speed, bool abort)
635 if (_transport_speed == speed) {
640 speed = min (8.0f, speed);
641 } else if (speed < 0) {
642 speed = max (-8.0f, speed);
645 if (transport_rolling() && speed == 0.0) {
647 if (synced_to_jack ()) {
648 _engine.transport_stop ();
650 stop_transport (abort);
653 } else if (transport_stopped() && speed == 1.0) {
655 if (synced_to_jack()) {
656 _engine.transport_start ();
663 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
664 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
669 if (actively_recording()) {
673 if (speed > 0.0f && _transport_frame == current_end_frame()) {
677 if (speed < 0.0f && _transport_frame == 0) {
683 /* if we are reversing relative to the current speed, or relative to the speed
684 before the last stop, then we have to do extra work.
687 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
688 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
691 _last_transport_speed = _transport_speed;
692 _transport_speed = speed;
694 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
695 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
696 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
700 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
701 schedule_butler_transport_work ();
707 Session::stop_transport (bool abort)
709 if (_transport_speed == 0.0f) {
713 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
714 _worst_output_latency > current_block_size)
717 /* we need to capture the audio that has still not yet been received by the system
718 at the time the stop is requested, so we have to roll past that time.
720 we want to declick before stopping, so schedule the autostop for one
721 block before the actual end. we'll declick in the subsequent block,
722 and then we'll really be stopped.
725 Event *ev = new Event (Event::StopOnce, Event::Replace,
726 _transport_frame + _worst_output_latency - current_block_size,
730 transport_sub_state |= StopPendingCapture;
731 pending_abort = abort;
735 if ((transport_sub_state & PendingDeclickOut) == 0) {
736 transport_sub_state |= PendingDeclickOut;
737 /* we'll be called again after the declick */
741 realtime_stop (abort);
742 schedule_butler_transport_work ();
746 Session::start_transport ()
748 _last_roll_location = _transport_frame;
750 /* if record status is Enabled, move it to Recording. if its
751 already Recording, move it to Disabled.
754 switch (record_status()) {
769 if (!synced_to_jack() || _exporting) {
770 actually_start_transport ();
772 waiting_to_start = true;
777 Session::actually_start_transport ()
779 waiting_to_start = false;
781 transport_sub_state |= PendingDeclickIn;
782 _transport_speed = 1.0;
784 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
785 (*i)->realtime_set_speed ((*i)->speed(), true);
788 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
790 TransportStateChange (); /* EMIT SIGNAL */
794 Session::post_transport ()
796 if (post_transport_work & PostTransportAudition) {
797 if (auditioner && auditioner->active()) {
798 process_function = &Session::process_audition;
800 process_function = &Session::process_with_events;
804 if (post_transport_work & PostTransportStop) {
806 transport_sub_state = 0;
809 if (post_transport_work & PostTransportLocate) {
811 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
816 transport_sub_state = 0;
822 post_transport_work = PostTransportWork (0);
826 Session::set_rf_speed (float speed)
829 cumulative_rf_motion = 0;
834 Session::reset_rf_scale (jack_nframes_t motion)
836 cumulative_rf_motion += motion;
838 if (cumulative_rf_motion < 4 * _current_frame_rate) {
840 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
842 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
854 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
856 bool reverse = false;
857 bool non_rt_required = false;
859 if (_transport_speed) {
860 error << _("please stop the transport before adjusting slave settings") << endmsg;
861 /* help out non-MVC friendly UI's by telling them the slave type changed */
862 ControlChanged (SlaveType); /* EMIT SIGNAL */
866 if (src == _slave_type) {
870 // if (src == JACK && Config->get_jack_time_master()) {
880 if (_transport_speed < 0.0) {
892 _slave = new MTC_Slave (*this, *_mtc_port);
895 catch (failed_constructor& err) {
900 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
903 _desired_transport_speed = _transport_speed;
907 _slave = new JACK_Slave (_engine.jack());
908 _desired_transport_speed = _transport_speed;
914 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
915 if (!(*i)->hidden()) {
916 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
917 non_rt_required = true;
919 (*i)->set_slaved (_slave);
924 reverse_diskstream_buffers ();
927 if (non_rt_required) {
928 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
929 schedule_butler_transport_work ();
933 ControlChanged (SlaveType); /* EMIT SIGNAL */
939 Session::reverse_diskstream_buffers ()
941 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
942 schedule_butler_transport_work ();
946 Session::set_diskstream_speed (DiskStream* stream, float speed)
948 if (stream->realtime_set_speed (speed, false)) {
949 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
950 schedule_butler_transport_work ();
956 Session::set_audio_range (list<AudioRange>& range)
958 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
959 ev->audio_range = range;
964 Session::request_play_range (bool yn)
966 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
971 Session::set_play_range (bool yn)
973 /* Called from event-processing context */
975 if (_play_range != yn) {
981 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
985 ControlChanged (PlayRange); /* EMIT SIGNAL */
990 Session::setup_auto_play ()
992 /* Called from event-processing context */
996 _clear_event_type (Event::RangeStop);
997 _clear_event_type (Event::RangeLocate);
1003 list<AudioRange>::size_type sz = current_audio_range.size();
1007 list<AudioRange>::iterator i = current_audio_range.begin();
1008 list<AudioRange>::iterator next;
1010 while (i != current_audio_range.end()) {
1015 /* locating/stopping is subject to delays for declicking.
1018 jack_nframes_t requested_frame = (*i).end;
1020 if (requested_frame > current_block_size) {
1021 requested_frame -= current_block_size;
1023 requested_frame = 0;
1026 if (next == current_audio_range.end()) {
1027 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1029 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1037 } else if (sz == 1) {
1039 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1044 /* now start rolling at the right place */
1046 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1051 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1054 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1056 request_locate (start, true);
1060 Session::engine_halted ()
1062 /* there will be no more calls to process(), so
1063 we'd better clean up for ourselves, right now.
1065 but first, make sure the butler is out of
1069 atomic_set (&butler_should_do_transport_work, 0);
1070 post_transport_work = PostTransportWork (0);
1073 realtime_stop (false);
1074 non_realtime_stop (false);
1075 transport_sub_state = 0;
1077 TransportStateChange (); /* EMIT SIGNAL */
1082 Session::xrun_recovery ()
1084 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1086 HaltOnXrun (); /* EMIT SIGNAL */
1088 /* it didn't actually halt, but we need
1089 to handle things in the same way.
1097 Session::update_latency_compensation (bool with_stop, bool abort)
1099 bool update_jack = false;
1101 if (_state_of_the_state & Deletion) {
1105 LockMonitor lm (route_lock, __LINE__, __FILE__);
1106 LockMonitor lm2 (diskstream_lock, __LINE__, __FILE__);
1107 _worst_track_latency = 0;
1109 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1111 (*i)->transport_stopped (abort, (post_transport_work & PostTransportLocate),
1112 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1115 jack_nframes_t old_latency = (*i)->signal_latency ();
1116 jack_nframes_t track_latency = (*i)->update_total_latency ();
1118 if (old_latency != track_latency) {
1122 if (!(*i)->hidden() && ((*i)->active())) {
1123 _worst_track_latency = max (_worst_track_latency, track_latency);
1127 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1128 (*i)->set_latency_delay (_worst_track_latency);
1131 /* tell JACK to play catch up */
1134 _engine.update_total_latencies ();
1137 set_worst_io_latencies (false);
1139 /* reflect any changes in latencies into capture offsets
1142 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1143 (*i)->set_capture_offset ();
1148 Session::update_latency_compensation_proxy (void* ignored)
1150 update_latency_compensation (false, false);