Tweak transmission of MMC on locate. Should fix #3121.
[ardour.git] / libs / ardour / session_transport.cc
1 /*
2     Copyright (C) 1999-2003 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cmath>
21 #include <cerrno>
22 #include <unistd.h>
23
24
25 #include "pbd/undo.h"
26 #include "pbd/error.h"
27 #include "pbd/enumwriter.h"
28 #include "pbd/pthread_utils.h"
29 #include "pbd/memento_command.h"
30
31 #include "midi++/mmc.h"
32 #include "midi++/port.h"
33
34 #include "ardour/ardour.h"
35 #include "ardour/audioengine.h"
36 #include "ardour/auditioner.h"
37 #include "ardour/butler.h"
38 #include "ardour/debug.h"
39 #include "ardour/location.h"
40 #include "ardour/session.h"
41 #include "ardour/slave.h"
42
43 #include "i18n.h"
44
45 using namespace std;
46 using namespace ARDOUR;
47 using namespace PBD;
48
49 void
50 Session::add_post_transport_work (PostTransportWork ptw)
51 {
52         PostTransportWork oldval;
53         PostTransportWork newval;
54         int tries = 0;
55
56         while (tries < 8) {
57                 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
58                 newval = PostTransportWork (oldval | ptw);
59                 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
60                         /* success */
61                         return;
62                 }
63         }
64
65         error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
66 }
67
68 void
69 Session::request_input_change_handling ()
70 {
71         if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
72                 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
73                 queue_event (ev);
74         }
75 }
76
77 void
78 Session::request_sync_source (Slave* new_slave)
79 {
80         SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
81         bool seamless;
82
83         seamless = Config->get_seamless_loop ();
84
85         if (dynamic_cast<JACK_Slave*>(new_slave)) {
86                 /* JACK cannot support seamless looping at present */
87                 Config->set_seamless_loop (false);
88         } else {
89                 /* reset to whatever the value was before we last switched slaves */
90                 Config->set_seamless_loop (_was_seamless);
91         }
92
93         /* save value of seamless from before the switch */
94         _was_seamless = seamless;
95
96         ev->slave = new_slave;
97         queue_event (ev);
98 }
99
100 void
101 Session::request_transport_speed (double speed)
102 {
103         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
104         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
105         queue_event (ev);
106 }
107
108 void
109 Session::request_track_speed (Track* tr, double speed)
110 {
111         SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
112         ev->set_ptr (tr);
113         queue_event (ev);
114 }
115
116 void
117 Session::request_stop (bool abort, bool clear_state)
118 {
119         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
120         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
121         queue_event (ev);
122 }
123
124 void
125 Session::request_locate (nframes_t target_frame, bool with_roll)
126 {
127         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
128         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
129         queue_event (ev);
130 }
131
132 void
133 Session::force_locate (nframes64_t target_frame, bool with_roll)
134 {
135         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
136         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
137         queue_event (ev);
138 }
139
140 void
141 Session::request_play_loop (bool yn, bool leave_rolling)
142 {
143         SessionEvent* ev;
144         Location *location = _locations.auto_loop_location();
145
146         if (location == 0 && yn) {
147                 error << _("Cannot loop - no loop range defined")
148                       << endmsg;
149                 return;
150         }
151
152         ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
153         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
154         queue_event (ev);
155
156         if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
157                 // request an immediate locate to refresh the tracks
158                 // after disabling looping
159                 request_locate (_transport_frame-1, false);
160         }
161 }
162
163 void
164 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
165 {
166         SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
167         if (range) {
168                 ev->audio_range = *range;
169         } else {
170                 ev->audio_range.clear ();
171         }
172         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
173         queue_event (ev);
174 }
175
176 void
177 Session::realtime_stop (bool abort, bool clear_state)
178 {
179         DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
180         PostTransportWork todo = PostTransportWork (0);
181
182         /* assume that when we start, we'll be moving forwards */
183
184         // FIXME: where should this really be? [DR]
185         //send_full_time_code();
186         deliver_mmc (MIDI::MachineControl::cmdStop, 0);
187         deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
188
189         if (_transport_speed < 0.0f) {
190                 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
191         } else {
192                 todo = PostTransportWork (todo | PostTransportStop);
193         }
194
195         if (actively_recording()) {
196
197                 /* move the transport position back to where the
198                    request for a stop was noticed. we rolled
199                    past that point to pick up delayed input (and/or to delick)
200                 */
201
202                 if (_worst_output_latency > current_block_size) {
203                         /* we rolled past the stop point to pick up data that had
204                            not yet arrived. move back to where the stop occured.
205                         */
206                         decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
207                 } else {
208                         decrement_transport_position (current_block_size);
209                 }
210
211                 /* the duration change is not guaranteed to have happened, but is likely */
212
213                 todo = PostTransportWork (todo | PostTransportDuration);
214         }
215
216         if (abort) {
217                 todo = PostTransportWork (todo | PostTransportAbort);
218         }
219
220         if (clear_state) {
221                 todo = PostTransportWork (todo | PostTransportClearSubstate);
222         }
223
224         if (todo) {
225                 add_post_transport_work (todo);
226         }
227
228         _clear_event_type (SessionEvent::StopOnce);
229         _clear_event_type (SessionEvent::RangeStop);
230         _clear_event_type (SessionEvent::RangeLocate);
231
232         /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
233         disable_record (true, (!Config->get_latched_record_enable() && clear_state));
234         
235         reset_slave_state ();
236
237         _transport_speed = 0;
238         _target_transport_speed = 0;
239
240         g_atomic_int_set (&_playback_load, 100);
241         g_atomic_int_set (&_capture_load, 100);
242
243         if (config.get_use_video_sync()) {
244                 waiting_for_sync_offset = true;
245         }
246
247         transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
248 }
249
250 void
251 Session::butler_transport_work ()
252 {
253   restart:
254         bool finished;
255         PostTransportWork ptw;
256         boost::shared_ptr<RouteList> r = routes.reader ();
257
258         int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
259         finished = true;
260         ptw = post_transport_work();
261
262         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
263
264         if (ptw & PostTransportAdjustPlaybackBuffering) {
265                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
266                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
267                         if (tr) {
268                                 tr->adjust_playback_buffering ();
269                                 /* and refill those buffers ... */
270                                 tr->non_realtime_locate (_transport_frame);
271                         }
272                 }
273                 
274         }
275
276         if (ptw & PostTransportAdjustCaptureBuffering) {
277                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
278                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
279                         if (tr) {
280                                 tr->adjust_capture_buffering ();
281                         }
282                 }
283         }
284
285         if (ptw & PostTransportCurveRealloc) {
286                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
287                         (*i)->curve_reallocate();
288                 }
289         }
290
291         if (ptw & PostTransportInputChange) {
292                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
293                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
294                         if (tr) {
295                                 tr->non_realtime_input_change ();
296                         }
297                 }
298         }
299
300         if (ptw & PostTransportSpeed) {
301                 non_realtime_set_speed ();
302         }
303
304         if (ptw & PostTransportReverse) {
305
306                 clear_clicks();
307                 cumulative_rf_motion = 0;
308                 reset_rf_scale (0);
309
310                 /* don't seek if locate will take care of that in non_realtime_stop() */
311
312                 if (!(ptw & PostTransportLocate)) {
313
314                         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
315                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
316                                 if (tr && !tr->hidden()) {
317                                         tr->non_realtime_locate (_transport_frame);
318                                 }
319                                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
320                                         /* new request, stop seeking, and start again */
321                                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
322                                         goto restart;
323                                 }
324                         }
325                 }
326         }
327
328         if (ptw & PostTransportLocate) {
329                 non_realtime_locate ();
330         }
331
332         if (ptw & PostTransportStop) {
333                 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
334                 if (!finished) {
335                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
336                         goto restart;
337                 }
338         }
339
340         if (ptw & PostTransportOverWrite) {
341                 non_realtime_overwrite (on_entry, finished);
342                 if (!finished) {
343                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
344                         goto restart;
345                 }
346         }
347
348         if (ptw & PostTransportAudition) {
349                 non_realtime_set_audition ();
350         }
351
352         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
353
354         DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
355 }
356
357 void
358 Session::non_realtime_set_speed ()
359 {
360         boost::shared_ptr<RouteList> rl = routes.reader();
361         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
362                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
363                 if (tr) {
364                         tr->non_realtime_set_speed ();
365                 }
366         }
367 }
368
369 void
370 Session::non_realtime_overwrite (int on_entry, bool& finished)
371 {
372         boost::shared_ptr<RouteList> rl = routes.reader();
373         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
374                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
375                 if (tr && tr->pending_overwrite ()) {
376                         tr->overwrite_existing_buffers ();
377                 }
378                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
379                         finished = false;
380                         return;
381                 }
382         }
383 }
384
385
386 void
387 Session::non_realtime_locate ()
388 {
389         boost::shared_ptr<RouteList> rl = routes.reader();
390         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
391                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
392                 if (tr) {
393                         tr->non_realtime_locate (_transport_frame);
394                 }
395         }
396 }
397
398
399 void
400 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
401 {
402         struct tm* now;
403         time_t     xnow;
404         bool       did_record;
405         bool       saved;
406         PostTransportWork ptw = post_transport_work();
407
408         did_record = false;
409         saved = false;
410
411         boost::shared_ptr<RouteList> rl = routes.reader();
412         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
413                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
414                 if (tr && tr->get_captured_frames () != 0) {
415                         did_record = true;
416                         break;
417                 }
418         }
419
420         /* stop and locate are merged here because they share a lot of common stuff */
421
422         time (&xnow);
423         now = localtime (&xnow);
424
425         if (auditioner) {
426                 auditioner->cancel_audition ();
427         }
428
429         clear_clicks();
430         cumulative_rf_motion = 0;
431         reset_rf_scale (0);
432
433         if (did_record) {
434                 begin_reversible_command ("capture");
435                 _have_captured = true;
436         }
437
438         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
439         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
440                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
441                 if (tr) {
442                         tr->transport_stopped_wallclock (*now, xnow, abort);
443                 }
444         }
445
446         boost::shared_ptr<RouteList> r = routes.reader ();
447
448         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
449                 if (!(*i)->is_hidden()) {
450                         (*i)->set_pending_declick (0);
451                 }
452         }
453
454         if (did_record) {
455                 commit_reversible_command ();
456         }
457
458         if (_engine.running()) {
459                 update_latency_compensation (true, abort);
460         }
461
462         bool const auto_return_enabled =
463                 (!config.get_external_sync() && config.get_auto_return());
464
465         if (auto_return_enabled ||
466             (ptw & PostTransportLocate) ||
467             (_requested_return_frame >= 0) ||
468             synced_to_jack()) {
469
470                 if (pending_locate_flush) {
471                         flush_all_inserts ();
472                 }
473
474                 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
475                     !(ptw & PostTransportLocate)) {
476
477                         /* no explicit locate queued */
478
479                         bool do_locate = false;
480
481                         if (_requested_return_frame >= 0) {
482
483                                 /* explicit return request pre-queued in event list. overrides everything else */
484                                 
485                                 cerr << "explicit auto-return to " << _requested_return_frame << endl;
486
487                                 _transport_frame = _requested_return_frame;
488                                 do_locate = true;
489
490                         } else {
491                                 if (config.get_auto_return()) {
492
493                                         if (play_loop) {
494
495                                                 /* don't try to handle loop play when synced to JACK */
496
497                                                 if (!synced_to_jack()) {
498
499                                                         Location *location = _locations.auto_loop_location();
500                                                         
501                                                         if (location != 0) {
502                                                                 _transport_frame = location->start();
503                                                         } else {
504                                                                 _transport_frame = _last_roll_location;
505                                                         }
506                                                         do_locate = true;
507                                                 }
508
509                                         } else if (_play_range) {
510
511                                                 /* return to start of range */
512
513                                                 if (!current_audio_range.empty()) {
514                                                         _transport_frame = current_audio_range.front().start;
515                                                         do_locate = true;
516                                                 }
517
518                                         } else {
519                                                 
520                                                 /* regular auto-return */
521                                                 
522                                                 _transport_frame = _last_roll_location;
523                                                 do_locate = true;
524                                         }
525                                 } 
526                         }
527
528                         _requested_return_frame = -1;                   
529
530                         if (do_locate) {
531                                 _engine.transport_locate (_transport_frame);
532                         }
533                 } 
534
535         }
536
537         /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
538         */
539
540         if (ptw & PostTransportClearSubstate) {
541                 _play_range = false;
542                 unset_play_loop ();
543         }
544
545         /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
546
547         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
548         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
549                 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
550                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
551                 if (tr && !tr->hidden()) {
552                         tr->non_realtime_locate (_transport_frame);
553                 }
554
555                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
556                         finished = false;
557                         /* we will be back */
558                         return;
559                 }
560         }
561
562         have_looped = false;
563
564         send_full_time_code (0);
565         deliver_mmc (MIDI::MachineControl::cmdStop, 0);
566         deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
567
568         if ((ptw & PostTransportLocate) && get_record_enabled()) {
569                 /* capture start has been changed, so save pending state */
570                 save_state ("", true);
571                 saved = true;
572         }
573
574         /* always try to get rid of this */
575
576         remove_pending_capture_state ();
577
578         /* save the current state of things if appropriate */
579
580         if (did_record && !saved) {
581                 save_state (_current_snapshot_name);
582         }
583
584         if (ptw & PostTransportStop) {
585                 _play_range = false;
586                 play_loop = false;
587         }
588
589         // can't cast away volatile so copy and emit that
590         nframes64_t tframe = _transport_frame;
591         PositionChanged (tframe); /* EMIT SIGNAL */
592         TransportStateChange (); /* EMIT SIGNAL */
593
594         /* and start it up again if relevant */
595
596         if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
597                 request_transport_speed (1.0);
598                 pending_locate_roll = false;
599         }
600 }
601
602 void
603 Session::check_declick_out ()
604 {
605         bool locate_required = transport_sub_state & PendingLocate;
606
607         /* this is called after a process() iteration. if PendingDeclickOut was set,
608            it means that we were waiting to declick the output (which has just been
609            done) before doing something else. this is where we do that "something else".
610
611            note: called from the audio thread.
612         */
613
614         if (transport_sub_state & PendingDeclickOut) {
615
616                 if (locate_required) {
617                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
618                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
619                 } else {
620                         stop_transport (pending_abort);
621                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
622                 }
623         }
624 }
625
626 void
627 Session::unset_play_loop ()
628 {
629         play_loop = false;
630         clear_events (SessionEvent::AutoLoop);
631         
632         // set all tracks to NOT use internal looping
633         boost::shared_ptr<RouteList> rl = routes.reader ();
634         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
635                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
636                 if (tr && !tr->hidden()) {
637                         tr->set_loop (0);
638                 }
639         }
640 }
641
642 void
643 Session::set_play_loop (bool yn)
644 {
645         /* Called from event-handling context */
646
647         Location *loc;
648
649         if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
650                 /* nothing to do, or can't change loop status while recording */
651                 return;
652         }
653         
654         set_dirty();
655         
656         if (yn && Config->get_seamless_loop() && synced_to_jack()) {
657                 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
658                                              "Recommend changing the configured options"), PROGRAM_NAME)
659                         << endmsg;
660                 return;
661         }
662         
663         if (yn) {
664
665                 play_loop = true;
666
667                 if (loc) {
668
669                         unset_play_range ();
670
671                         if (Config->get_seamless_loop()) {
672                                 // set all tracks to use internal looping
673                                 boost::shared_ptr<RouteList> rl = routes.reader ();
674                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
675                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
676                                         if (tr && !tr->hidden()) {
677                                                 tr->set_loop (loc);
678                                         }
679                                 }
680                         }
681                         else {
682                                 // set all tracks to NOT use internal looping
683                                 boost::shared_ptr<RouteList> rl = routes.reader ();
684                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
685                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
686                                         if (tr && !tr->hidden()) {
687                                                 tr->set_loop (0);
688                                         }
689                                 }
690                         }
691                         
692                         /* put the loop event into the event list */
693                         
694                         SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
695                         merge_event (event);
696
697                         /* locate to start of loop and roll. If doing seamless loop, force a 
698                            locate+buffer refill even if we are positioned there already.
699                         */
700
701                         start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
702                 }
703
704         } else {
705
706                 unset_play_loop ();
707         }
708
709         TransportStateChange ();
710 }
711 void
712 Session::flush_all_inserts ()
713 {
714         boost::shared_ptr<RouteList> r = routes.reader ();
715
716         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
717                 (*i)->flush_processors ();
718         }
719 }
720
721 void
722 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
723 {
724         if (synced_to_jack()) {
725
726                 double sp;
727                 nframes64_t pos;
728
729                 _slave->speed_and_position (sp, pos);
730
731                 if (target_frame != pos) {
732
733                         /* tell JACK to change transport position, and we will
734                            follow along later in ::follow_slave()
735                         */
736
737                         _engine.transport_locate (target_frame);
738
739                         if (sp != 1.0f && with_roll) {
740                                 _engine.transport_start ();
741                         }
742
743                 }
744
745         } else {
746                 locate (target_frame, with_roll, with_flush, with_loop, force);
747         }
748 }
749
750 int
751 Session::micro_locate (nframes_t distance)
752 {
753         boost::shared_ptr<RouteList> rl = routes.reader();
754         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
755                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
756                 if (tr && !tr->can_internal_playback_seek (distance)) {
757                         return -1;
758                 }
759         }
760
761         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
762                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
763                 if (tr) {
764                         tr->internal_playback_seek (distance);
765                 }
766         }
767
768         _transport_frame += distance;
769         return 0;
770 }
771
772 /** @param with_mmc true to send a MMC locate command when the locate is done */
773 void
774 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
775 {
776         if (actively_recording() && !with_loop) {
777                 return;
778         }
779
780         if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
781                 if (with_roll) {
782                         set_transport_speed (1.0, false);
783                 }
784                 loop_changing = false;
785                 return;
786         }
787
788         // Update Timecode time
789         // [DR] FIXME: find out exactly where this should go below
790         _transport_frame = target_frame;
791         timecode_time(_transport_frame, transmitting_timecode_time);
792         outbound_mtc_timecode_frame = _transport_frame;
793         next_quarter_frame_to_send = 0;
794
795         if (_transport_speed && (!with_loop || loop_changing)) {
796                 /* schedule a declick. we'll be called again when its done */
797
798                 if (!(transport_sub_state & PendingDeclickOut)) {
799                         transport_sub_state |= (PendingDeclickOut|PendingLocate);
800                         pending_locate_frame = target_frame;
801                         pending_locate_roll = with_roll;
802                         pending_locate_flush = with_flush;
803                         return;
804                 }
805         }
806
807         if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
808                 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
809         }
810
811         if (force || !with_loop || loop_changing) {
812
813                 PostTransportWork todo = PostTransportLocate;
814
815                 if (with_roll) {
816                         todo = PostTransportWork (todo | PostTransportRoll);
817                 } 
818
819                 add_post_transport_work (todo);
820                 _butler->schedule_transport_work ();
821
822         } else {
823
824                 /* this is functionally what clear_clicks() does but with a tentative lock */
825
826                 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
827
828                 if (clickm.locked()) {
829
830                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
831                                 delete *i;
832                         }
833
834                         clicks.clear ();
835                 }
836         }
837
838         if (with_roll) {
839                 /* switch from input if we're going to roll */
840                 if (Config->get_monitoring_model() == HardwareMonitoring) {
841
842                         boost::shared_ptr<RouteList> rl = routes.reader();
843                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
844                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
845                                 if (tr && tr->record_enabled ()) {
846                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
847                                         tr->monitor_input (!config.get_auto_input());
848                                 }
849                         }
850                 }
851         } else {
852                 /* otherwise we're going to stop, so do the opposite */
853                 if (Config->get_monitoring_model() == HardwareMonitoring) {
854
855                         boost::shared_ptr<RouteList> rl = routes.reader();
856                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
857                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
858                                 if (tr && tr->record_enabled ()) {
859                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
860                                         tr->monitor_input (true);
861                                 }
862                         }
863                 }
864         }
865
866         /* cancel looped playback if transport pos outside of loop range */
867         if (play_loop) {
868                 Location* al = _locations.auto_loop_location();
869
870                 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
871                         // cancel looping directly, this is called from event handling context
872                         set_play_loop (false);
873                 }
874                 else if (al && _transport_frame == al->start()) {
875                         if (with_loop) {
876                                 // this is only necessary for seamless looping
877
878                                 boost::shared_ptr<RouteList> rl = routes.reader();
879                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
880                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
881                                         if (tr && tr->record_enabled ()) {
882                                                 // tell it we've looped, so it can deal with the record state
883                                                 tr->transport_looped(_transport_frame);
884                                         }
885                                 }
886                         }
887                         have_looped = true;
888                         TransportLooped(); // EMIT SIGNAL
889                 }
890         }
891
892         loop_changing = false;
893
894         _send_timecode_update = true;
895
896         if (with_mmc) {
897                 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
898         }
899
900         Located (); /* EMIT SIGNAL */
901 }
902
903 /** Set the transport speed.
904  * @param speed New speed
905  * @param abort
906  */
907 void
908 Session::set_transport_speed (double speed, bool abort, bool clear_state)
909 {
910         DEBUG_TRACE (DEBUG::Transport, string_compose ("Set transport speed to %1, abort = %2 clear_state = %3, current = %4\n", speed, abort, clear_state, _transport_speed));
911
912         if (_transport_speed == speed) {
913                 return;
914         }
915
916         _target_transport_speed = fabs(speed);
917
918         /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
919            and user needs. We really need CD-style "skip" playback for ffwd and rewind.
920         */
921
922         if (speed > 0) {
923                 speed = min (8.0, speed);
924         } else if (speed < 0) {
925                 speed = max (-8.0, speed);
926         }
927
928         if (transport_rolling() && speed == 0.0) {
929
930                 /* we are rolling and we want to stop */
931
932                 if (Config->get_monitoring_model() == HardwareMonitoring)
933                 {
934                         boost::shared_ptr<RouteList> rl = routes.reader();
935                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
936                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
937                                 if (tr && tr->record_enabled ()) {
938                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
939                                         tr->monitor_input (true);
940                                 }
941                         }
942                 }
943
944                 if (synced_to_jack ()) {
945                         if (clear_state) {
946                                 /* do this here because our response to the slave won't 
947                                    take care of it.
948                                 */
949                                 _play_range = false;
950                                 unset_play_loop ();
951                         }
952                         _engine.transport_stop ();
953                 } else {
954                         stop_transport (abort);
955                 }
956
957         } else if (transport_stopped() && speed == 1.0) {
958
959                 /* we are stopped and we want to start rolling at speed 1 */
960
961                 if (Config->get_monitoring_model() == HardwareMonitoring) {
962
963                         boost::shared_ptr<RouteList> rl = routes.reader();
964                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
965                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
966                                 if (config.get_auto_input() && tr && tr->record_enabled ()) {
967                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
968                                         tr->monitor_input (false);
969                                 }
970                         }
971                 }
972
973                 if (synced_to_jack()) {
974                         _engine.transport_start ();
975                 } else {
976                         start_transport ();
977                 }
978
979         } else {
980
981                 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
982                         warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
983                                                    PROGRAM_NAME)
984                                 << endmsg;
985                         return;
986                 }
987
988                 if (actively_recording()) {
989                         return;
990                 }
991
992                 if (speed > 0.0 && _transport_frame == current_end_frame()) {
993                         return;
994                 }
995
996                 if (speed < 0.0 && _transport_frame == 0) {
997                         return;
998                 }
999
1000                 clear_clicks ();
1001
1002                 /* if we are reversing relative to the current speed, or relative to the speed
1003                    before the last stop, then we have to do extra work.
1004                 */
1005                 
1006                 PostTransportWork todo = PostTransportWork (0);
1007
1008                 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1009                         todo = PostTransportWork (todo | PostTransportReverse);
1010                         _last_roll_or_reversal_location = _transport_frame;
1011                 }
1012
1013                 _last_transport_speed = _transport_speed;
1014                 _transport_speed = speed;
1015
1016                 boost::shared_ptr<RouteList> rl = routes.reader();
1017                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1018                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1019                         if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1020                                 todo = PostTransportWork (todo | PostTransportSpeed);
1021                                 break;
1022                         }
1023                 }
1024
1025                 if (todo) {
1026                         add_post_transport_work (todo);
1027                         _butler->schedule_transport_work ();
1028                 }
1029         }
1030 }
1031
1032
1033 /** Stop the transport.  */
1034 void
1035 Session::stop_transport (bool abort, bool clear_state)
1036 {
1037         if (_transport_speed == 0.0f) {
1038                 return;
1039         }
1040
1041         if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1042
1043                 boost::shared_ptr<RouteList> rl = routes.reader();
1044                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1045                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1046                         if (tr) {
1047                                 tr->prepare_to_stop (_transport_frame);
1048                         }
1049                 }
1050
1051                 /* we need to capture the audio that has still not yet been received by the system
1052                    at the time the stop is requested, so we have to roll past that time.
1053
1054                    we want to declick before stopping, so schedule the autostop for one
1055                    block before the actual end. we'll declick in the subsequent block,
1056                    and then we'll really be stopped.
1057                 */
1058
1059                 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1060                                        _transport_frame + _worst_output_latency - current_block_size,
1061                                        0, 0, abort);
1062
1063                 merge_event (ev);
1064                 transport_sub_state |= StopPendingCapture;
1065                 pending_abort = abort;
1066                 return;
1067         }
1068
1069
1070         if ((transport_sub_state & PendingDeclickOut) == 0) {
1071
1072                 if (!(transport_sub_state & StopPendingCapture)) {
1073                         boost::shared_ptr<RouteList> rl = routes.reader();
1074                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1075                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1076                                 if (tr) {
1077                                         tr->prepare_to_stop (_transport_frame);
1078                                 }
1079                         }
1080                 }
1081                 
1082                 transport_sub_state |= PendingDeclickOut;
1083                 /* we'll be called again after the declick */
1084                 pending_abort = abort;
1085                 return;
1086         }
1087
1088         realtime_stop (abort, clear_state);
1089         _butler->schedule_transport_work ();
1090 }
1091
1092 void
1093 Session::start_transport ()
1094 {
1095         _last_roll_location = _transport_frame;
1096         _last_roll_or_reversal_location = _transport_frame;
1097         
1098         have_looped = false;
1099
1100         /* if record status is Enabled, move it to Recording. if its
1101            already Recording, move it to Disabled.
1102         */
1103
1104         switch (record_status()) {
1105         case Enabled:
1106                 if (!config.get_punch_in()) {
1107                         enable_record ();
1108                 }
1109                 break;
1110
1111         case Recording:
1112                 if (!play_loop) {
1113                         disable_record (false);
1114                 }
1115                 break;
1116
1117         default:
1118                 break;
1119         }
1120
1121         transport_sub_state |= PendingDeclickIn;
1122
1123         _transport_speed = 1.0;
1124         _target_transport_speed = 1.0;
1125
1126         boost::shared_ptr<RouteList> rl = routes.reader();
1127         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1128                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1129                 if (tr) {
1130                         tr->realtime_set_speed (tr->speed(), true);
1131                 }
1132         }
1133
1134         deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
1135
1136         TransportStateChange (); /* EMIT SIGNAL */
1137 }
1138
1139 /** Do any transport work in the audio thread that needs to be done after the
1140  * transport thread is finished.  Audio thread, realtime safe.
1141  */
1142 void
1143 Session::post_transport ()
1144 {
1145         PostTransportWork ptw = post_transport_work ();
1146
1147         if (ptw & PostTransportAudition) {
1148                 if (auditioner && auditioner->auditioning()) {
1149                         process_function = &Session::process_audition;
1150                 } else {
1151                         process_function = &Session::process_with_events;
1152                 }
1153         }
1154
1155         if (ptw & PostTransportStop) {
1156
1157                 transport_sub_state = 0;
1158         }
1159
1160         if (ptw & PostTransportLocate) {
1161
1162                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1163                         start_transport ();
1164
1165                 } else {
1166                         transport_sub_state = 0;
1167                 }
1168         }
1169
1170         set_next_event ();
1171         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1172            know were handled ?
1173         */
1174         set_post_transport_work (PostTransportWork (0));
1175 }
1176
1177 void
1178 Session::reset_rf_scale (nframes_t motion)
1179 {
1180         cumulative_rf_motion += motion;
1181
1182         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1183                 rf_scale = 1;
1184         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1185                 rf_scale = 4;
1186         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1187                 rf_scale = 10;
1188         } else {
1189                 rf_scale = 100;
1190         }
1191
1192         if (motion != 0) {
1193                 set_dirty();
1194         }
1195 }
1196
1197 void
1198 Session::use_sync_source (Slave* new_slave)
1199 {
1200         /* Runs in process() context */
1201
1202         bool non_rt_required = false;
1203
1204         /* XXX this deletion is problematic because we're in RT context */
1205
1206         delete _slave;
1207         _slave = new_slave;
1208
1209         boost::shared_ptr<RouteList> rl = routes.reader();
1210         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1211                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1212                 if (tr && !tr->hidden()) {
1213                         if (tr->realtime_set_speed (tr->speed(), true)) {
1214                                 non_rt_required = true;
1215                         }
1216                         tr->set_slaved (_slave != 0);
1217                 }
1218         }
1219
1220         if (non_rt_required) {
1221                 add_post_transport_work (PostTransportSpeed);
1222                 _butler->schedule_transport_work ();
1223         }
1224
1225         set_dirty();
1226 }
1227
1228 void
1229 Session::drop_sync_source ()
1230 {
1231         request_sync_source (0);
1232 }
1233
1234 void
1235 Session::switch_to_sync_source (SyncSource src)
1236 {
1237         Slave* new_slave;
1238
1239         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1240
1241         switch (src) {
1242         case MTC:
1243                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1244                         return;
1245                 }
1246
1247                 if (_mtc_port) {
1248                         try {
1249                                 new_slave = new MTC_Slave (*this, *_mtc_port);
1250                         }
1251
1252                         catch (failed_constructor& err) {
1253                                 return;
1254                         }
1255
1256                 } else {
1257                         error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1258                         return;
1259                 }
1260                 break;
1261
1262         case MIDIClock:
1263                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1264                         return;
1265                 }
1266
1267                 if (_midi_clock_port) {
1268                         try {
1269                                 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1270                         }
1271
1272                         catch (failed_constructor& err) {
1273                                 return;
1274                         }
1275
1276                 } else {
1277                         error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1278                         return;
1279                 }
1280                 break;
1281
1282         case JACK:
1283                 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1284                         return;
1285                 }
1286
1287                 new_slave = new JACK_Slave (_engine.jack());
1288                 break;
1289                 
1290         default:
1291                 new_slave = 0;
1292                 break;
1293         };
1294
1295         request_sync_source (new_slave);
1296 }
1297
1298 void
1299 Session::reverse_track_buffers ()
1300 {
1301         add_post_transport_work (PostTransportReverse);
1302         _butler->schedule_transport_work ();
1303 }
1304
1305 void
1306 Session::set_track_speed (Track* track, double speed)
1307 {
1308         if (track->realtime_set_speed (speed, false)) {
1309                 add_post_transport_work (PostTransportSpeed);
1310                 _butler->schedule_transport_work ();
1311                 set_dirty ();
1312         }
1313 }
1314
1315 void
1316 Session::unset_play_range ()
1317 {
1318         _play_range = false;
1319         _clear_event_type (SessionEvent::RangeStop);
1320         _clear_event_type (SessionEvent::RangeLocate);
1321 }
1322
1323 void
1324 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1325 {
1326         SessionEvent* ev;
1327
1328         /* Called from event-processing context */
1329
1330         unset_play_range ();
1331         
1332         if (range.empty()) {
1333                 /* _play_range set to false in unset_play_range()
1334                  */
1335                 if (!leave_rolling) {
1336                         /* stop transport */
1337                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1338                         merge_event (ev);
1339                 }
1340                 return;
1341         }
1342
1343         _play_range = true;
1344
1345         /* cancel loop play */
1346         unset_play_loop ();
1347
1348         list<AudioRange>::size_type sz = range.size();
1349         
1350         if (sz > 1) {
1351                 
1352                 list<AudioRange>::iterator i = range.begin(); 
1353                 list<AudioRange>::iterator next;
1354                 
1355                 while (i != range.end()) {
1356                         
1357                         next = i;
1358                         ++next;
1359                         
1360                         /* locating/stopping is subject to delays for declicking.
1361                          */
1362                         
1363                         nframes_t requested_frame = (*i).end;
1364                         
1365                         if (requested_frame > current_block_size) {
1366                                 requested_frame -= current_block_size;
1367                         } else {
1368                                 requested_frame = 0;
1369                         }
1370                         
1371                         if (next == range.end()) {
1372                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1373                         } else {
1374                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1375                         }
1376                         
1377                         merge_event (ev);
1378                         
1379                         i = next;
1380                 }
1381                 
1382         } else if (sz == 1) {
1383
1384                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1385                 merge_event (ev);
1386                 
1387         } 
1388
1389         /* save range so we can do auto-return etc. */
1390
1391         current_audio_range = range;
1392
1393         /* now start rolling at the right place */
1394
1395         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1396         merge_event (ev);
1397         
1398         TransportStateChange ();
1399 }
1400
1401 void
1402 Session::request_bounded_roll (nframes_t start, nframes_t end)
1403 {
1404         AudioRange ar (start, end, 0);
1405         list<AudioRange> lar;
1406
1407         lar.push_back (ar);
1408         request_play_range (&lar, true);
1409 }
1410 void
1411 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1412 {
1413         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1414         ev->target2_frame = start;
1415         queue_event (ev);
1416 }
1417
1418 void
1419 Session::engine_halted ()
1420 {
1421         bool ignored;
1422
1423         /* there will be no more calls to process(), so
1424            we'd better clean up for ourselves, right now.
1425
1426            but first, make sure the butler is out of
1427            the picture.
1428         */
1429
1430         g_atomic_int_set (&_butler->should_do_transport_work, 0);
1431         set_post_transport_work (PostTransportWork (0));
1432         _butler->stop ();
1433
1434         realtime_stop (false, true);
1435         non_realtime_stop (false, 0, ignored);
1436         transport_sub_state = 0;
1437
1438         TransportStateChange (); /* EMIT SIGNAL */
1439 }
1440
1441
1442 void
1443 Session::xrun_recovery ()
1444 {
1445         // can't cast away volatile so copy and emit that
1446         nframes64_t tframe = _transport_frame;
1447         Xrun (tframe); //EMIT SIGNAL
1448
1449         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1450
1451                 /* it didn't actually halt, but we need
1452                    to handle things in the same way.
1453                 */
1454
1455                 engine_halted();
1456         }
1457 }
1458
1459 void
1460 Session::route_processors_changed (RouteProcessorChange c)
1461 {
1462         if (c.type == RouteProcessorChange::MeterPointChange) {
1463                 return;
1464         }
1465
1466         update_latency_compensation (false, false);
1467         resort_routes ();
1468 }
1469
1470 void
1471 Session::update_latency_compensation (bool with_stop, bool abort)
1472 {
1473         bool update_jack = false;
1474         PostTransportWork ptw;
1475
1476         if (_state_of_the_state & Deletion) {
1477                 return;
1478         }
1479
1480         _worst_track_latency = 0;
1481         ptw = post_transport_work();
1482
1483 #undef DEBUG_LATENCY
1484 #ifdef DEBUG_LATENCY
1485         cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1486 #endif
1487
1488         boost::shared_ptr<RouteList> r = routes.reader ();
1489
1490         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1491
1492                 if (with_stop) {
1493                         (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1494                 }
1495
1496                 nframes_t old_latency = (*i)->output()->signal_latency ();
1497                 nframes_t track_latency = (*i)->update_total_latency ();
1498
1499                 if (old_latency != track_latency) {
1500                         (*i)->input()->update_port_total_latencies ();
1501                         (*i)->output()->update_port_total_latencies ();
1502                         update_jack = true;
1503                 }
1504
1505                 if (!(*i)->is_hidden() && ((*i)->active())) {
1506                         _worst_track_latency = max (_worst_track_latency, track_latency);
1507                 }
1508         }
1509
1510         if (update_jack) {
1511                 _engine.update_total_latencies ();
1512         }
1513
1514 #ifdef DEBUG_LATENCY
1515         cerr << "\tworst was " << _worst_track_latency << endl;
1516 #endif
1517
1518         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1519                 (*i)->set_latency_delay (_worst_track_latency);
1520         }
1521
1522         set_worst_io_latencies ();
1523
1524         /* reflect any changes in latencies into capture offsets
1525         */
1526         
1527         boost::shared_ptr<RouteList> rl = routes.reader();
1528         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1529                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1530                 if (tr) {
1531                         tr->set_capture_offset ();
1532                 }
1533         }
1534 }
1535
1536 void
1537 Session::allow_auto_play (bool yn)
1538 {
1539         auto_play_legal = yn;
1540 }
1541
1542 void
1543 Session::reset_jack_connection (jack_client_t* jack)
1544 {
1545         JACK_Slave* js;
1546
1547         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1548                 js->reset_client (jack);
1549         }
1550 }
1551
1552 bool
1553 Session::maybe_stop (nframes_t limit)
1554 {
1555        if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1556                if (synced_to_jack () && config.get_jack_time_master ()) {
1557                        _engine.transport_stop ();
1558                } else if (!synced_to_jack ()) {
1559                        stop_transport ();
1560                }
1561                return true;
1562        }
1563        return false;
1564 }