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