Clean up MMC transmission a bit, and make sure that it is all done from one thread.
[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         _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
187         Timecode::Time time;
188         timecode_time_subframes (_transport_frame, time);
189         _mmc->send (MIDI::MachineControlCommand (time));
190
191         if (_transport_speed < 0.0f) {
192                 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
193         } else {
194                 todo = PostTransportWork (todo | PostTransportStop);
195         }
196
197         if (actively_recording()) {
198
199                 /* move the transport position back to where the
200                    request for a stop was noticed. we rolled
201                    past that point to pick up delayed input (and/or to delick)
202                 */
203
204                 if (_worst_output_latency > current_block_size) {
205                         /* we rolled past the stop point to pick up data that had
206                            not yet arrived. move back to where the stop occured.
207                         */
208                         decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
209                 } else {
210                         decrement_transport_position (current_block_size);
211                 }
212
213                 /* the duration change is not guaranteed to have happened, but is likely */
214
215                 todo = PostTransportWork (todo | PostTransportDuration);
216         }
217
218         if (abort) {
219                 todo = PostTransportWork (todo | PostTransportAbort);
220         }
221
222         if (clear_state) {
223                 todo = PostTransportWork (todo | PostTransportClearSubstate);
224         }
225
226         if (todo) {
227                 add_post_transport_work (todo);
228         }
229
230         _clear_event_type (SessionEvent::StopOnce);
231         _clear_event_type (SessionEvent::RangeStop);
232         _clear_event_type (SessionEvent::RangeLocate);
233
234         /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
235         disable_record (true, (!Config->get_latched_record_enable() && clear_state));
236         
237         reset_slave_state ();
238
239         _transport_speed = 0;
240         _target_transport_speed = 0;
241
242         g_atomic_int_set (&_playback_load, 100);
243         g_atomic_int_set (&_capture_load, 100);
244
245         if (config.get_use_video_sync()) {
246                 waiting_for_sync_offset = true;
247         }
248
249         transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
250 }
251
252 void
253 Session::butler_transport_work ()
254 {
255   restart:
256         bool finished;
257         PostTransportWork ptw;
258         boost::shared_ptr<RouteList> r = routes.reader ();
259
260         int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
261         finished = true;
262         ptw = post_transport_work();
263
264         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
265
266         if (ptw & PostTransportAdjustPlaybackBuffering) {
267                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
268                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
269                         if (tr) {
270                                 tr->adjust_playback_buffering ();
271                                 /* and refill those buffers ... */
272                                 tr->non_realtime_locate (_transport_frame);
273                         }
274                 }
275                 
276         }
277
278         if (ptw & PostTransportAdjustCaptureBuffering) {
279                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
280                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
281                         if (tr) {
282                                 tr->adjust_capture_buffering ();
283                         }
284                 }
285         }
286
287         if (ptw & PostTransportCurveRealloc) {
288                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
289                         (*i)->curve_reallocate();
290                 }
291         }
292
293         if (ptw & PostTransportInputChange) {
294                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
295                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
296                         if (tr) {
297                                 tr->non_realtime_input_change ();
298                         }
299                 }
300         }
301
302         if (ptw & PostTransportSpeed) {
303                 non_realtime_set_speed ();
304         }
305
306         if (ptw & PostTransportReverse) {
307
308                 clear_clicks();
309                 cumulative_rf_motion = 0;
310                 reset_rf_scale (0);
311
312                 /* don't seek if locate will take care of that in non_realtime_stop() */
313
314                 if (!(ptw & PostTransportLocate)) {
315
316                         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
317                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
318                                 if (tr && !tr->hidden()) {
319                                         tr->non_realtime_locate (_transport_frame);
320                                 }
321                                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
322                                         /* new request, stop seeking, and start again */
323                                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
324                                         goto restart;
325                                 }
326                         }
327                 }
328         }
329
330         if (ptw & PostTransportLocate) {
331                 non_realtime_locate ();
332         }
333
334         if (ptw & PostTransportStop) {
335                 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
336                 if (!finished) {
337                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
338                         goto restart;
339                 }
340         }
341
342         if (ptw & PostTransportOverWrite) {
343                 non_realtime_overwrite (on_entry, finished);
344                 if (!finished) {
345                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
346                         goto restart;
347                 }
348         }
349
350         if (ptw & PostTransportAudition) {
351                 non_realtime_set_audition ();
352         }
353
354         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
355
356         DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
357 }
358
359 void
360 Session::non_realtime_set_speed ()
361 {
362         boost::shared_ptr<RouteList> rl = routes.reader();
363         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
364                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
365                 if (tr) {
366                         tr->non_realtime_set_speed ();
367                 }
368         }
369 }
370
371 void
372 Session::non_realtime_overwrite (int on_entry, bool& finished)
373 {
374         boost::shared_ptr<RouteList> rl = routes.reader();
375         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
376                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
377                 if (tr && tr->pending_overwrite ()) {
378                         tr->overwrite_existing_buffers ();
379                 }
380                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
381                         finished = false;
382                         return;
383                 }
384         }
385 }
386
387
388 void
389 Session::non_realtime_locate ()
390 {
391         boost::shared_ptr<RouteList> rl = routes.reader();
392         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
393                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
394                 if (tr) {
395                         tr->non_realtime_locate (_transport_frame);
396                 }
397         }
398 }
399
400
401 void
402 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
403 {
404         struct tm* now;
405         time_t     xnow;
406         bool       did_record;
407         bool       saved;
408         PostTransportWork ptw = post_transport_work();
409
410         did_record = false;
411         saved = false;
412
413         boost::shared_ptr<RouteList> rl = routes.reader();
414         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
415                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
416                 if (tr && tr->get_captured_frames () != 0) {
417                         did_record = true;
418                         break;
419                 }
420         }
421
422         /* stop and locate are merged here because they share a lot of common stuff */
423
424         time (&xnow);
425         now = localtime (&xnow);
426
427         if (auditioner) {
428                 auditioner->cancel_audition ();
429         }
430
431         clear_clicks();
432         cumulative_rf_motion = 0;
433         reset_rf_scale (0);
434
435         if (did_record) {
436                 begin_reversible_command ("capture");
437                 _have_captured = true;
438         }
439
440         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
441         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
442                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
443                 if (tr) {
444                         tr->transport_stopped_wallclock (*now, xnow, abort);
445                 }
446         }
447
448         boost::shared_ptr<RouteList> r = routes.reader ();
449
450         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
451                 if (!(*i)->is_hidden()) {
452                         (*i)->set_pending_declick (0);
453                 }
454         }
455
456         if (did_record) {
457                 commit_reversible_command ();
458         }
459
460         if (_engine.running()) {
461                 update_latency_compensation (true, abort);
462         }
463
464         bool const auto_return_enabled =
465                 (!config.get_external_sync() && config.get_auto_return());
466
467         if (auto_return_enabled ||
468             (ptw & PostTransportLocate) ||
469             (_requested_return_frame >= 0) ||
470             synced_to_jack()) {
471
472                 if (pending_locate_flush) {
473                         flush_all_inserts ();
474                 }
475
476                 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
477                     !(ptw & PostTransportLocate)) {
478
479                         /* no explicit locate queued */
480
481                         bool do_locate = false;
482
483                         if (_requested_return_frame >= 0) {
484
485                                 /* explicit return request pre-queued in event list. overrides everything else */
486                                 
487                                 cerr << "explicit auto-return to " << _requested_return_frame << endl;
488
489                                 _transport_frame = _requested_return_frame;
490                                 do_locate = true;
491
492                         } else {
493                                 if (config.get_auto_return()) {
494
495                                         if (play_loop) {
496
497                                                 /* don't try to handle loop play when synced to JACK */
498
499                                                 if (!synced_to_jack()) {
500
501                                                         Location *location = _locations.auto_loop_location();
502                                                         
503                                                         if (location != 0) {
504                                                                 _transport_frame = location->start();
505                                                         } else {
506                                                                 _transport_frame = _last_roll_location;
507                                                         }
508                                                         do_locate = true;
509                                                 }
510
511                                         } else if (_play_range) {
512
513                                                 /* return to start of range */
514
515                                                 if (!current_audio_range.empty()) {
516                                                         _transport_frame = current_audio_range.front().start;
517                                                         do_locate = true;
518                                                 }
519
520                                         } else {
521                                                 
522                                                 /* regular auto-return */
523                                                 
524                                                 _transport_frame = _last_roll_location;
525                                                 do_locate = true;
526                                         }
527                                 } 
528                         }
529
530                         _requested_return_frame = -1;                   
531
532                         if (do_locate) {
533                                 _engine.transport_locate (_transport_frame);
534                         }
535                 } 
536
537         }
538
539         /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
540         */
541
542         if (ptw & PostTransportClearSubstate) {
543                 _play_range = false;
544                 unset_play_loop ();
545         }
546
547         /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
548
549         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
550         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
551                 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
552                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
553                 if (tr && !tr->hidden()) {
554                         tr->non_realtime_locate (_transport_frame);
555                 }
556
557                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
558                         finished = false;
559                         /* we will be back */
560                         return;
561                 }
562         }
563
564         have_looped = false;
565
566         send_full_time_code (0);
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                 Timecode::Time time;
898                 timecode_time_subframes (_transport_frame, time);
899                 _mmc->send (MIDI::MachineControlCommand (time));
900         }
901
902         Located (); /* EMIT SIGNAL */
903 }
904
905 /** Set the transport speed.
906  * @param speed New speed
907  * @param abort
908  */
909 void
910 Session::set_transport_speed (double speed, bool abort, bool clear_state)
911 {
912         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));
913
914         if (_transport_speed == speed) {
915                 return;
916         }
917
918         _target_transport_speed = fabs(speed);
919
920         /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
921            and user needs. We really need CD-style "skip" playback for ffwd and rewind.
922         */
923
924         if (speed > 0) {
925                 speed = min (8.0, speed);
926         } else if (speed < 0) {
927                 speed = max (-8.0, speed);
928         }
929
930         if (transport_rolling() && speed == 0.0) {
931
932                 /* we are rolling and we want to stop */
933
934                 if (Config->get_monitoring_model() == HardwareMonitoring)
935                 {
936                         boost::shared_ptr<RouteList> rl = routes.reader();
937                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
938                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
939                                 if (tr && tr->record_enabled ()) {
940                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
941                                         tr->monitor_input (true);
942                                 }
943                         }
944                 }
945
946                 if (synced_to_jack ()) {
947                         if (clear_state) {
948                                 /* do this here because our response to the slave won't 
949                                    take care of it.
950                                 */
951                                 _play_range = false;
952                                 unset_play_loop ();
953                         }
954                         _engine.transport_stop ();
955                 } else {
956                         stop_transport (abort);
957                 }
958
959         } else if (transport_stopped() && speed == 1.0) {
960
961                 /* we are stopped and we want to start rolling at speed 1 */
962
963                 if (Config->get_monitoring_model() == HardwareMonitoring) {
964
965                         boost::shared_ptr<RouteList> rl = routes.reader();
966                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
967                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
968                                 if (config.get_auto_input() && tr && tr->record_enabled ()) {
969                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
970                                         tr->monitor_input (false);
971                                 }
972                         }
973                 }
974
975                 if (synced_to_jack()) {
976                         _engine.transport_start ();
977                 } else {
978                         start_transport ();
979                 }
980
981         } else {
982
983                 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
984                         warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
985                                                    PROGRAM_NAME)
986                                 << endmsg;
987                         return;
988                 }
989
990                 if (actively_recording()) {
991                         return;
992                 }
993
994                 if (speed > 0.0 && _transport_frame == current_end_frame()) {
995                         return;
996                 }
997
998                 if (speed < 0.0 && _transport_frame == 0) {
999                         return;
1000                 }
1001
1002                 clear_clicks ();
1003
1004                 /* if we are reversing relative to the current speed, or relative to the speed
1005                    before the last stop, then we have to do extra work.
1006                 */
1007                 
1008                 PostTransportWork todo = PostTransportWork (0);
1009
1010                 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1011                         todo = PostTransportWork (todo | PostTransportReverse);
1012                         _last_roll_or_reversal_location = _transport_frame;
1013                 }
1014
1015                 _last_transport_speed = _transport_speed;
1016                 _transport_speed = speed;
1017
1018                 boost::shared_ptr<RouteList> rl = routes.reader();
1019                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1020                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1021                         if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1022                                 todo = PostTransportWork (todo | PostTransportSpeed);
1023                                 break;
1024                         }
1025                 }
1026
1027                 if (todo) {
1028                         add_post_transport_work (todo);
1029                         _butler->schedule_transport_work ();
1030                 }
1031         }
1032 }
1033
1034
1035 /** Stop the transport.  */
1036 void
1037 Session::stop_transport (bool abort, bool clear_state)
1038 {
1039         if (_transport_speed == 0.0f) {
1040                 return;
1041         }
1042
1043         if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1044
1045                 boost::shared_ptr<RouteList> rl = routes.reader();
1046                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1047                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1048                         if (tr) {
1049                                 tr->prepare_to_stop (_transport_frame);
1050                         }
1051                 }
1052
1053                 /* we need to capture the audio that has still not yet been received by the system
1054                    at the time the stop is requested, so we have to roll past that time.
1055
1056                    we want to declick before stopping, so schedule the autostop for one
1057                    block before the actual end. we'll declick in the subsequent block,
1058                    and then we'll really be stopped.
1059                 */
1060
1061                 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1062                                        _transport_frame + _worst_output_latency - current_block_size,
1063                                        0, 0, abort);
1064
1065                 merge_event (ev);
1066                 transport_sub_state |= StopPendingCapture;
1067                 pending_abort = abort;
1068                 return;
1069         }
1070
1071
1072         if ((transport_sub_state & PendingDeclickOut) == 0) {
1073
1074                 if (!(transport_sub_state & StopPendingCapture)) {
1075                         boost::shared_ptr<RouteList> rl = routes.reader();
1076                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1077                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1078                                 if (tr) {
1079                                         tr->prepare_to_stop (_transport_frame);
1080                                 }
1081                         }
1082                 }
1083                 
1084                 transport_sub_state |= PendingDeclickOut;
1085                 /* we'll be called again after the declick */
1086                 pending_abort = abort;
1087                 return;
1088         }
1089
1090         realtime_stop (abort, clear_state);
1091         _butler->schedule_transport_work ();
1092 }
1093
1094 void
1095 Session::start_transport ()
1096 {
1097         _last_roll_location = _transport_frame;
1098         _last_roll_or_reversal_location = _transport_frame;
1099         
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         Timecode::Time time;
1137         timecode_time_subframes (_transport_frame, time);
1138         _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1139
1140         TransportStateChange (); /* EMIT SIGNAL */
1141 }
1142
1143 /** Do any transport work in the audio thread that needs to be done after the
1144  * transport thread is finished.  Audio thread, realtime safe.
1145  */
1146 void
1147 Session::post_transport ()
1148 {
1149         PostTransportWork ptw = post_transport_work ();
1150
1151         if (ptw & PostTransportAudition) {
1152                 if (auditioner && auditioner->auditioning()) {
1153                         process_function = &Session::process_audition;
1154                 } else {
1155                         process_function = &Session::process_with_events;
1156                 }
1157         }
1158
1159         if (ptw & PostTransportStop) {
1160
1161                 transport_sub_state = 0;
1162         }
1163
1164         if (ptw & PostTransportLocate) {
1165
1166                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1167                         start_transport ();
1168
1169                 } else {
1170                         transport_sub_state = 0;
1171                 }
1172         }
1173
1174         set_next_event ();
1175         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1176            know were handled ?
1177         */
1178         set_post_transport_work (PostTransportWork (0));
1179 }
1180
1181 void
1182 Session::reset_rf_scale (nframes_t motion)
1183 {
1184         cumulative_rf_motion += motion;
1185
1186         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1187                 rf_scale = 1;
1188         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1189                 rf_scale = 4;
1190         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1191                 rf_scale = 10;
1192         } else {
1193                 rf_scale = 100;
1194         }
1195
1196         if (motion != 0) {
1197                 set_dirty();
1198         }
1199 }
1200
1201 void
1202 Session::use_sync_source (Slave* new_slave)
1203 {
1204         /* Runs in process() context */
1205
1206         bool non_rt_required = false;
1207
1208         /* XXX this deletion is problematic because we're in RT context */
1209
1210         delete _slave;
1211         _slave = new_slave;
1212
1213         boost::shared_ptr<RouteList> rl = routes.reader();
1214         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1215                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1216                 if (tr && !tr->hidden()) {
1217                         if (tr->realtime_set_speed (tr->speed(), true)) {
1218                                 non_rt_required = true;
1219                         }
1220                         tr->set_slaved (_slave != 0);
1221                 }
1222         }
1223
1224         if (non_rt_required) {
1225                 add_post_transport_work (PostTransportSpeed);
1226                 _butler->schedule_transport_work ();
1227         }
1228
1229         set_dirty();
1230 }
1231
1232 void
1233 Session::drop_sync_source ()
1234 {
1235         request_sync_source (0);
1236 }
1237
1238 void
1239 Session::switch_to_sync_source (SyncSource src)
1240 {
1241         Slave* new_slave;
1242
1243         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1244
1245         switch (src) {
1246         case MTC:
1247                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1248                         return;
1249                 }
1250
1251                 if (_mtc_port) {
1252                         try {
1253                                 new_slave = new MTC_Slave (*this, *_mtc_port);
1254                         }
1255
1256                         catch (failed_constructor& err) {
1257                                 return;
1258                         }
1259
1260                 } else {
1261                         error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1262                         return;
1263                 }
1264                 break;
1265
1266         case MIDIClock:
1267                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1268                         return;
1269                 }
1270
1271                 if (_midi_clock_port) {
1272                         try {
1273                                 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1274                         }
1275
1276                         catch (failed_constructor& err) {
1277                                 return;
1278                         }
1279
1280                 } else {
1281                         error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1282                         return;
1283                 }
1284                 break;
1285
1286         case JACK:
1287                 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1288                         return;
1289                 }
1290
1291                 new_slave = new JACK_Slave (_engine.jack());
1292                 break;
1293                 
1294         default:
1295                 new_slave = 0;
1296                 break;
1297         };
1298
1299         request_sync_source (new_slave);
1300 }
1301
1302 void
1303 Session::reverse_track_buffers ()
1304 {
1305         add_post_transport_work (PostTransportReverse);
1306         _butler->schedule_transport_work ();
1307 }
1308
1309 void
1310 Session::set_track_speed (Track* track, double speed)
1311 {
1312         if (track->realtime_set_speed (speed, false)) {
1313                 add_post_transport_work (PostTransportSpeed);
1314                 _butler->schedule_transport_work ();
1315                 set_dirty ();
1316         }
1317 }
1318
1319 void
1320 Session::unset_play_range ()
1321 {
1322         _play_range = false;
1323         _clear_event_type (SessionEvent::RangeStop);
1324         _clear_event_type (SessionEvent::RangeLocate);
1325 }
1326
1327 void
1328 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1329 {
1330         SessionEvent* ev;
1331
1332         /* Called from event-processing context */
1333
1334         unset_play_range ();
1335         
1336         if (range.empty()) {
1337                 /* _play_range set to false in unset_play_range()
1338                  */
1339                 if (!leave_rolling) {
1340                         /* stop transport */
1341                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1342                         merge_event (ev);
1343                 }
1344                 return;
1345         }
1346
1347         _play_range = true;
1348
1349         /* cancel loop play */
1350         unset_play_loop ();
1351
1352         list<AudioRange>::size_type sz = range.size();
1353         
1354         if (sz > 1) {
1355                 
1356                 list<AudioRange>::iterator i = range.begin(); 
1357                 list<AudioRange>::iterator next;
1358                 
1359                 while (i != range.end()) {
1360                         
1361                         next = i;
1362                         ++next;
1363                         
1364                         /* locating/stopping is subject to delays for declicking.
1365                          */
1366                         
1367                         nframes_t requested_frame = (*i).end;
1368                         
1369                         if (requested_frame > current_block_size) {
1370                                 requested_frame -= current_block_size;
1371                         } else {
1372                                 requested_frame = 0;
1373                         }
1374                         
1375                         if (next == range.end()) {
1376                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1377                         } else {
1378                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1379                         }
1380                         
1381                         merge_event (ev);
1382                         
1383                         i = next;
1384                 }
1385                 
1386         } else if (sz == 1) {
1387
1388                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1389                 merge_event (ev);
1390                 
1391         } 
1392
1393         /* save range so we can do auto-return etc. */
1394
1395         current_audio_range = range;
1396
1397         /* now start rolling at the right place */
1398
1399         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1400         merge_event (ev);
1401         
1402         TransportStateChange ();
1403 }
1404
1405 void
1406 Session::request_bounded_roll (nframes_t start, nframes_t end)
1407 {
1408         AudioRange ar (start, end, 0);
1409         list<AudioRange> lar;
1410
1411         lar.push_back (ar);
1412         request_play_range (&lar, true);
1413 }
1414 void
1415 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1416 {
1417         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1418         ev->target2_frame = start;
1419         queue_event (ev);
1420 }
1421
1422 void
1423 Session::engine_halted ()
1424 {
1425         bool ignored;
1426
1427         /* there will be no more calls to process(), so
1428            we'd better clean up for ourselves, right now.
1429
1430            but first, make sure the butler is out of
1431            the picture.
1432         */
1433
1434         g_atomic_int_set (&_butler->should_do_transport_work, 0);
1435         set_post_transport_work (PostTransportWork (0));
1436         _butler->stop ();
1437
1438         realtime_stop (false, true);
1439         non_realtime_stop (false, 0, ignored);
1440         transport_sub_state = 0;
1441
1442         TransportStateChange (); /* EMIT SIGNAL */
1443 }
1444
1445
1446 void
1447 Session::xrun_recovery ()
1448 {
1449         // can't cast away volatile so copy and emit that
1450         nframes64_t tframe = _transport_frame;
1451         Xrun (tframe); //EMIT SIGNAL
1452
1453         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1454
1455                 /* it didn't actually halt, but we need
1456                    to handle things in the same way.
1457                 */
1458
1459                 engine_halted();
1460         }
1461 }
1462
1463 void
1464 Session::route_processors_changed (RouteProcessorChange c)
1465 {
1466         if (c.type == RouteProcessorChange::MeterPointChange) {
1467                 return;
1468         }
1469
1470         update_latency_compensation (false, false);
1471         resort_routes ();
1472 }
1473
1474 void
1475 Session::update_latency_compensation (bool with_stop, bool abort)
1476 {
1477         bool update_jack = false;
1478         PostTransportWork ptw;
1479
1480         if (_state_of_the_state & Deletion) {
1481                 return;
1482         }
1483
1484         _worst_track_latency = 0;
1485         ptw = post_transport_work();
1486
1487 #undef DEBUG_LATENCY
1488 #ifdef DEBUG_LATENCY
1489         cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1490 #endif
1491
1492         boost::shared_ptr<RouteList> r = routes.reader ();
1493
1494         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1495
1496                 if (with_stop) {
1497                         (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1498                 }
1499
1500                 nframes_t old_latency = (*i)->output()->signal_latency ();
1501                 nframes_t track_latency = (*i)->update_total_latency ();
1502
1503                 if (old_latency != track_latency) {
1504                         (*i)->input()->update_port_total_latencies ();
1505                         (*i)->output()->update_port_total_latencies ();
1506                         update_jack = true;
1507                 }
1508
1509                 if (!(*i)->is_hidden() && ((*i)->active())) {
1510                         _worst_track_latency = max (_worst_track_latency, track_latency);
1511                 }
1512         }
1513
1514         if (update_jack) {
1515                 _engine.update_total_latencies ();
1516         }
1517
1518 #ifdef DEBUG_LATENCY
1519         cerr << "\tworst was " << _worst_track_latency << endl;
1520 #endif
1521
1522         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1523                 (*i)->set_latency_delay (_worst_track_latency);
1524         }
1525
1526         set_worst_io_latencies ();
1527
1528         /* reflect any changes in latencies into capture offsets
1529         */
1530         
1531         boost::shared_ptr<RouteList> rl = routes.reader();
1532         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1533                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1534                 if (tr) {
1535                         tr->set_capture_offset ();
1536                 }
1537         }
1538 }
1539
1540 void
1541 Session::allow_auto_play (bool yn)
1542 {
1543         auto_play_legal = yn;
1544 }
1545
1546 void
1547 Session::reset_jack_connection (jack_client_t* jack)
1548 {
1549         JACK_Slave* js;
1550
1551         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1552                 js->reset_client (jack);
1553         }
1554 }
1555
1556 bool
1557 Session::maybe_stop (nframes_t limit)
1558 {
1559        if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1560                if (synced_to_jack () && config.get_jack_time_master ()) {
1561                        _engine.transport_stop ();
1562                } else if (!synced_to_jack ()) {
1563                        stop_transport ();
1564                }
1565                return true;
1566        }
1567        return false;
1568 }