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