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