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