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