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